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
转换过程:
- pages/ 根目录,不参与命名
- video/ - 文件夹名,转换为 video
- [name]-[id]/ - 动态参数文件夹,转换为 name-id
- [[episode]] - 可选动态参数文件,转换为 episode
- 最终组合:video-name-id-episode
更多示例:
// 示例 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
navigateTo
// 基本跳转
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
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)
NuxtLink
- 用于模板中的声明式导航跳转
<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]]
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模式,在路由切换时会等待页面的异步数据获取完成:
- 同步的异步操作阻塞了路由跳转
// 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会阻塞整个页面渲染