路由
约 1251 字大约 4 分钟
2026-02-04
重要
Nuxt 路由采用 文件系统路由:app/pages 下的文件自动生成路由
最佳实践
- 动态参数务必校验:
definePageMeta({ validate })防止非法访问 - 导航优先用
NuxtLink,减少手写router.push - 中间件只做 "准入判断",不要做重请求
- 路由结构保持扁平清晰,过深会降低可读性
核心概念
基于文件的路由
app/pages 中的文件与目录会自动映射为路由,如果项目里没有 app/pages,Nuxt 不会启用 vue-router
app
pages
index.vue
…
about.vue /about
posts
index.vue /posts
[id].vue /posts/:id
docs
[...slug].vue /docs/:slug(.*)*
[[lang]].vue /:lang?
(marketing)
pricing.vue /pricing
动态路由
Nuxt 常见的文件路由命名可以分为:动态参数、可选参数、捕获所有、路由分组,当路由匹配完成后,可以通过 useRoute() 读取当前路由信息。
<script setup lang="ts">
const route = useRoute()
// /posts/123 → route.params.id = '123'
console.log(route.params.id)
</script>页面元信息
在页面中用 definePageMeta 声明布局、路由中间件、校验逻辑等:
<script setup lang="ts">
definePageMeta({
title: '文章详情',
layout: 'docs',
middleware: ['auth'],
validate: (route) => /^\d+$/.test(route.params.id as string),
})
</script>页面导航
NuxtLink
在 Nuxt 中,站内跳转优先使用 NuxtLink,它基于客户端路由导航,不会像原生 <a> 一样触发整页刷新,且 NuxtLink 默认带预取(prefetch),进入可视区时会预加载目标页面
<template>
<nav class="flex gap-3">
<NuxtLink to="/">Home</NuxtLink>
<NuxtLink to="/about">About</NuxtLink>
<NuxtLink :to="{ name: 'posts-id', params: { id: 1 } }">Post</NuxtLink>
</nav>
</template>编程式导航
当跳转由事件触发时,通常使用编程式导航。在 Nuxt 中可优先使用 navigateTo,或者直接使用 router.push
<script setup lang="ts">
const router = useRouter()
function goToPost(id: number) {
navigateTo(`/posts/${id}`)
// 或:
// router.push({ name: 'posts-id', params: { id } })
}
</script>路由校验
路由校验 validate 用于在进入页面前做 路由参数合法性校验,通常适用于动态路由的校验
返回值语义
- 返回
true:放行 - 返回
false:触发 404 - 返回对象(
{ statusCode, statusMessage }):进入错误页并显示自定义状态
笔记
validate 更适合做轻量 "格式校验";登录态与权限判断建议放在路由中间件
<script setup lang="ts">
definePageMeta({
validate: (route) => /^\d+$/.test(route.params.id as string),
})
</script><script setup lang="ts">
definePageMeta({
validate: (route) => {
const id = route.params.id as string
if (/^\d+$/.test(id)) {
return true
}
return {
statusCode: 400,
statusMessage: '参数 id 必须是数字',
}
},
})
</script>全局错误页
全局错误页 error.vue 是 Nuxt 的全局错误兜底页面。当路由、页面渲染或中间件流程抛出错误时,Nuxt 会暂时中断当前页面渲染,改为渲染 error.vue
触发全局错误页最常见的来源有
validate返回false(通常表现为 404)validate返回{ statusCode, statusMessage }- 中间件或页面逻辑里
createError(...)/abortNavigation(createError(...))
当发生以上情况时,Nuxt 会渲染 app/error.vue(若未提供则使用内置错误页)
<template>
<main class="error-page">
<h1>{{ statusCode }}</h1>
<p>{{ message }}</p>
<button @click="resetToHome">
返回首页
</button>
<details v-if="import.meta.dev">
<summary>错误详情(仅开发环境)</summary>
<pre>{{ props.error }}</pre>
</details>
</main>
</template>
<script setup lang="ts">
import type { NuxtError } from '#app'
const props = defineProps<{
error: NuxtError
}>()
const statusCode = computed(() => props.error.statusCode ?? 500)
const message = computed(() =>
props.error.statusMessage ?? getDefaultMessage(statusCode.value),
)
function getDefaultMessage(code: number): string {
const map: Record<number, string> = {
404: '页面未找到',
403: '无权限访问该页面',
500: '服务器内部错误',
}
return map[code] || '发生未知错误'
}
const resetToHome = () => clearError({ redirect: '/' })
</script>导航守卫
onBeforeRouteLeave / onBeforeRouteUpdate 这类导航守卫用于处理 组件内的导航交互,例如离开页面前二次确认、同组件复用时监听参数变化
与路由中间件的区别是:中间件侧重于 "路由准入控制",而导航守卫偏 "组件交互控制"
<script setup lang="ts">
const isDirty = ref(false)
onBeforeRouteLeave(() => {
if (isDirty.value) {
return window.confirm('内容未保存,确定离开?')
}
})
onBeforeRouteUpdate(() => {
// 同一组件复用但路由变化时触发
})
</script>路由规则
路由规则 routeRules 用于 按路由粒度 配置渲染与缓存策略(基于 Nitro)。常用于:静态化、关闭 SSR、设置 SWR 缓存、重定向等
笔记
routeRules 是部署层面的策略,适合 "全局一致" 的路由配置,页面级逻辑仍应优先使用 definePageMeta、中间件或组件内逻辑
export default defineNuxtConfig({
routeRules: {
'/': { prerender: true }, // 构建期静态化
'/about': { ssr: true }, // 强制 SSR
'/dashboard': { ssr: false }, // 仅客户端渲染
'/products/**': { swr: true }, // 缓存并后台更新
'/legacy': { redirect: '/docs' }, // 路由重定向
},
})