路由系统
Nuxt 的路由基于 vue-router,但你几乎不用手写配置。app/pages/ 下每个文件就是一条路由 —— 自动分包、自动预取、自动类型。
文件式路由
app/pages/
├── index.vue → /
├── about.vue → /about
└── posts/
├── index.vue → /posts
└── [id].vue → /posts/:id
Nuxt 会生成完整的类型化路由树,<NuxtLink> 的 to 值也会带类型。
动态段
方括号即 params:
<!-- app/pages/posts/[id].vue -->
<script setup lang="ts">
const route = useRoute()
console.log(route.params.id) // string
</script>
多个参数也 OK:app/pages/users/[userId]/posts/[postId].vue → /users/:userId/posts/:postId。
Catch-all:app/pages/docs/[...slug].vue 会匹配 /docs/a/b/c,route.params.slug = ['a', 'b', 'c']。
嵌套路由
让 parent.vue 和 parent/ 目录共存,在父组件里放 <NuxtPage />:
<!-- app/pages/settings.vue -->
<template>
<section>
<aside><!-- 导航 --></aside>
<NuxtPage />
</section>
</template>
app/pages/
├── settings.vue
└── settings/
├── profile.vue → /settings/profile
└── billing.vue → /settings/billing
<NuxtLink> 导航
应用内跳转一律用 <NuxtLink>:
<template>
<nav>
<NuxtLink to="/">首页</NuxtLink>
<NuxtLink to="/about">关于</NuxtLink>
<NuxtLink :to="{ name: 'posts-id', params: { id: 1 } }">文章 1</NuxtLink>
</nav>
</template>
它会:
- 渲染真正的
<a>(对无障碍友好)。 - 链接进入视口时自动预取组件与 payload。
- Hydration 之后走客户端跳转,不会整页刷新。
- 自动加上
.router-link-active/.router-link-exact-active类名。
想临时关掉预取:
<NuxtLink to="/heavy" :prefetch="false">Heavy page</NuxtLink>
程序式导航
<script setup lang="ts">
const router = useRouter()
function openPost (id: number) {
router.push(`/posts/${id}`)
}
</script>
在中间件、插件、事件处理器里优先使用 navigateTo():
export default defineNuxtRouteMiddleware((to) => {
if (!to.path.startsWith('/public')) return navigateTo('/login')
})
路由中间件
三种形态:
- 内联:直接写在页面的
definePageMeta({ middleware: (to) => {…} })里。 - 命名:文件放在
app/middleware/auth.ts,页面手动声明使用。 - 全局:
app/middleware/foo.global.ts,每次导航都会跑。
// app/middleware/auth.ts
export default defineNuxtRouteMiddleware((to) => {
const { user } = useUserSession()
if (!user.value) return navigateTo('/login')
})
<script setup lang="ts">
definePageMeta({ middleware: 'auth' })
</script>
路由中间件只在 Vue(客户端 & SSR)层执行。服务端/API 请求走
server/middleware/。
路由校验
用 validate 校验参数:
<script setup lang="ts">
definePageMeta({
validate (route) {
return typeof route.params.id === 'string' && /^\d+$/.test(route.params.id)
},
})
</script>
返回假值会触发 404;返回 { status, statusText } 可以自定义响应。
definePageMeta 概览
<script setup lang="ts">
definePageMeta({
layout: 'admin', // 指定布局
middleware: ['auth'], // 路由中间件
pageTransition: false, // 关闭过渡
validate: (r) => true, // 校验
key: (r) => r.path, // 重渲染策略
})
</script>
在 /posts/1 → /posts/2 这种相同路由不同参数的场景下,加 key 可以让组件重新创建。
小结
- 把
.vue文件丢进app/pages/,路由就已经有了。 - 应用内跳转一律
<NuxtLink>,获得预取与过渡。 - 鉴权、重定向、守卫交给中间件。
definePageMeta用来声明布局、中间件、校验等。