路由
Nuxt 的一个核心功能是文件系统路由。app/pages/
目录中的每个 Vue 文件都会创建一个对应的 URL(或路由),用来显示该文件的内容。通过对每个页面使用动态导入,Nuxt 利用代码拆分(code-splitting)来只发送请求路由所需的最小 JavaScript 代码。
页面
Nuxt 的路由基于 vue-router,并且会根据 app/pages/
目录 中每个组件的文件名自动生成对应的路由。
该文件系统路由通过命名约定来创建动态和嵌套路由:
-| pages/
---| about.vue
---| index.vue
---| posts/
-----| [id].vue
{
"routes": [
{
"path": "/about",
"component": "pages/about.vue"
},
{
"path": "/",
"component": "pages/index.vue"
},
{
"path": "/posts/:id",
"component": "pages/posts/[id].vue"
}
]
}
导航
<NuxtLink>
组件用于链接页面之间。它渲染一个带有 href
属性的 <a>
标签,属性值是页面的路由地址。应用水合(hydration)完成后,页面跳转将由 JavaScript 通过更新浏览器 URL 实现,这样可以避免完全刷新页面,并允许动画过渡效果。
当客户端视口中出现 <NuxtLink>
时,Nuxt 会自动预获取该链接页面的组件和负载(生成页面内容),从而实现更快的导航体验。
<template>
<header>
<nav>
<ul>
<li><NuxtLink to="/about">关于</NuxtLink></li>
<li><NuxtLink to="/posts/1">文章 1</NuxtLink></li>
<li><NuxtLink to="/posts/2">文章 2</NuxtLink></li>
</ul>
</nav>
</header>
</template>
路由参数
useRoute()
组合式函数可用于 Vue 组件的 <script setup>
块或 setup()
方法中,用以访问当前路由的详细信息。
<script setup lang="ts">
const route = useRoute()
// 访问 /posts/1 时,route.params.id 的值为 1
console.log(route.params.id)
</script>
路由中间件
Nuxt 提供了一个可自定义的路由中间件框架,可在整个应用中使用,适合抽离导航特定路由前需要执行的代码。
路由中间件有三种类型:
- 匿名(或内联)路由中间件,即直接定义在使用它的页面中。
- 命名路由中间件,放置在
app/middleware/
目录,使用时会通过异步导入自动加载。(注意:中间件名称会规范化为 kebab-case,比如someMiddleware
会变成some-middleware
。) - 全局路由中间件,放置在
app/middleware/
目录,文件名带有.global
后缀,会在每次路由变化时自动执行。
auth
中间件保护 /dashboard
页面的示例:
export default defineNuxtRouteMiddleware((to, from) => {
// isAuthenticated() 是一个示例方法,用于验证用户是否已认证
if (isAuthenticated() === false) {
return navigateTo('/login')
}
})
<script setup lang="ts">
definePageMeta({
middleware: 'auth',
})
</script>
<template>
<h1>欢迎来到你的仪表盘</h1>
</template>
路由验证
Nuxt 通过在每个想要验证的页面中使用 definePageMeta()
下的 validate
属性,提供路由验证功能。
validate
属性接受当前 route
作为参数。你可以返回布尔值来决定该路由是否为该页面的有效路由。返回 false
会触发 404 错误。也可以直接返回带有 statusCode
/statusMessage
的对象来自定义错误信息。
如果验证需求更复杂,可以使用匿名路由中间件来实现。
<script setup lang="ts">
definePageMeta({
validate (route) {
// 检查 id 是否全由数字组成
return typeof route.params.id === 'string' && /^\d+$/.test(route.params.id)
},
})
</script>