跳到主要内容

nuxt路由

动态路由​

写法含义描述
[param].vue必填动态参数(标准动态路由)
[[param]].vue可选动态参数(参数可有可无)
[...param].vue捕获所有剩余路径(catch-all)
[[...param]].vue可选的剩余路径(optional catch-all)

双括号​

  • 双括号 [[page]] 表示可选参数

  • 支持的URL格式:

    • /drama/New-Release ✅ (page参数不存在,默认为第1页)
    • /drama/New-Release/2 ✅ (page=2)

1、URL更简洁 - 第1页不需要显示 /1

2、SEO友好 - 主要页面URL更短

3、用户体验 - 符合用户习惯,第1页通常不显示页码

单括号​

  • 单括号 [page] 表示必填参数
  • 支持的URL格式:
    • /drama/New-Release ❌ (404,因为缺少page参数)
    • /drama/New-Release/2 ✅ (page=2)

文件路径到路由名称的转换规则​

基本规则:

  • 文件夹名和文件名用 - 连接

  • 动态参数 [param] 转换为 param

  • 可选参数 [[param]] 也转换为 param

  • 嵌套文件夹用 - 连接

例子

  • 文件路径:pages/video/[name]-[id]/[[episode]].vue
    • 生成的路由名称:video-name-id-episode

转换过程:

  1. pages/ 根目录,不参与命名
    • video/ - 文件夹名,转换为 video
    • [name]-[id]/ - 动态参数文件夹,转换为 name-id
    • [[episode]] - 可选动态参数文件,转换为 episode
    • 最终组合:video-name-id-episode

更多示例:

ts
// 示例 1:简单动态路由
// 文件:pages/user/[id].vue
// 路由名:user-id

// 示例 2:多参数动态路由
// 文件:pages/blog/[category]/[slug].vue
// 路由名:blog-category-slug

// 示例 3:可选参数
// 文件:pages/products/[category]/[[page]].vue
// 路由名:products-category-page

// 示例 4:catch-all 路由
// 文件:pages/docs/[...slug].vue
// 路由名:docs-slug

// 示例 5:可选 catch-all 路由
// 文件:pages/[...slug].vue
// 路由名:slug

中文路由匹配问题​

  • 中文字符可能会导致 Nuxt 路由匹配问题,从而出现 500 错误

路由跳转​

  • navigateTo
  • vueRouter
ts
// 基本跳转
await navigateTo('/about')

// 带参数跳转
await navigateTo('/user/123')

// 对象形式跳转
await navigateTo({
path: '/user',
query: { id: 123 }
})

// 替换当前路由(不保留历史记录)
await navigateTo('/about', { replace: true })

// 外部链接跳转
await navigateTo('https://example.com', { external: true })

vueRouter​

ts
const router = useRouter()

// 基本跳转
router.push('/about')

// 带参数跳转
router.push({
path: '/user',
query: { id: 123 }
})

// 命名路由跳转
router.push({
name: 'user-detail',
params: { id: 123 }
})

// 替换当前路由
router.replace('/about')

// 后退
router.back()

// 前进
router.forward()

// 跳转到指定历史记录
router.go(-1)
  • 用于模板中的声明式导航跳转
vue
<template>
<!-- 基本链接 -->
<NuxtLink to="/about">关于我们</NuxtLink>

<!-- 带参数 -->
<NuxtLink :to="{ path: '/user', query: { id: 123 } }">
用户详情
</NuxtLink>

<!-- 外部链接 -->
<NuxtLink to="https://example.com" external>
外部链接
</NuxtLink>

<!-- 替换当前路由 -->
<NuxtLink to="/about" replace>
替换当前页面
</NuxtLink>
</template>

动态路由​

nuxt会根据pages目录下的文件结构自动生成路由名称

  • 如页面路径为pages\video\[name]-[id]\[[episode]]
ts
router.push({
name:'video-name-id-episode',
params:{
...route.params,
name: 'series_name',
id: 'series_id',
episode: 'series_episode'
}
})

// 或者使用路径方式
router.push(`/video/${name}-${id}/${episode}`)

/ 使用navigateTo跳转
await navigateTo({
name: 'video-name-id-episode',
params: {
name: 'series_name',
id: 'series_id',
episode: 'series_episode'
}
})

路由跳转阻塞问题​

路由跳转等待接口请求完成的主要原因是:

  • SSR模式下的数据预取机制
    • Nuxt默认使用SSR模式,在路由切换时会等待页面的异步数据获取完成:
  • 同步的异步操作阻塞了路由跳转
ts
// pages/user/[id].vue
<script setup>
// 这会阻塞路由跳转,直到数据获取完成
const initData = async() => {
await $fetch(`/api/users/${route.params.id}`)
}
// await会阻塞页面渲染
await initdata()
</script>

解决方案

  • 1、使用 lazy: true 进行懒加载

    • 加了lazy就不会阻塞路由跳转,页面会先渲染再加载数据
  • 2、使用 useLazyFetch 等非阻塞API

  • 3、移除await

    • await会阻塞页面渲染,当await执行完之后,页面才会进行渲染
    • await会阻塞整个页面渲染