Nuxt 的一个核心功能是文件系统路由器。pages/目录下的每个 Vue 文件都会创建一个相应的 URL(或路由)来显示该文件的内容。通过为每个页面使用动态导入,Nuxt 利用代码拆分为所请求的路由提供最少的 JavaScript。
Nuxt 路由基于vue-router,并根据pages/目录下创建的每个组件的文件名生成路由。
该文件系统路由使用命名约定来创建动态和嵌套路由:
// 示例目录结构
pages/
--| about.vue
--| index.vue
--| posts/
----| [id].vue
上面的目录结构,Nuxt 会生成如下的路由表:
{
"routes": [
{
"path": "/about",
"component": "pages/about.vue"
},
{
"path": "/",
"component": "pages/index.vue"
},
{
"path": "/posts/:id",
"component": "pages/posts/[id].vue"
}
]
}
index.vue 和 about.vue 的代码之前文章已提供,此处补上 posts/[id].vue 文件的内容:
// pages/posts/[id].vue
@ posts page
组件在页面之间建立链接。它渲染了一个标签,其 href 属性被设置为页面的路径。一旦应用程序水合,页面转换将通过更新浏览器 URL 在 JavaScript 中执行。这可以防止全页面刷新,并允许动画过渡。
当进入客户端视口时,Nuxt 将自动提前预取组件和链接页面的有效载荷(生成的页面),从而加快导航速度。
下面的代码示例,是在默认布局文件中:
// layouts/default.vue
此时可以点击页面顶部的导航切换页面了。
在块或 Vue 组件的setup()方法,通过组合函数useRoute()以访问当前路由的详细信息。
正好,可以在 pages/posts/[id].vue 文件中来实践一下:
// pages/posts/[id].vue
@ posts page #id {{ route.params.id }}
此时,点击页面顶部的导航链接就可以看到效果了。
Nuxt 提供了一个可定制的路由中间件框架,您可以在整个应用程序中使用,非常适合在导航到特定路由之前提取您想要运行的代码。
路由中间件运行于 Nuxt 应用程序的 Vue 部分。尽管名称相似,但它们与服务器中间件完全不同,后者运行于应用程序的 Nitro 服务器部分。
路由中间件有三种:
middleware/目录中,当在页面中使用时将通过异步导入自动加载。(注意:路由中间件的名称被规范化为kebab-case 横线命名法,因此someMiddleware变成了some-middleware。)middleware/目录下(且带有.global的后缀),每次路由变更时都会自动运行。示例:auth中间件保护/dashboard页面
// middleware/auth.ts
export default defineNuxtRouteMiddleware((to, from) => {
console.log("@", to, from);
if (isAuthenticated() === false) {
return navigateTo("/login");
}
});
export const isAuthenticated = (): boolean => {
//TODO: 此处定义验证用户身份的代码逻辑
return false;
};
// pages/login.vue
@ login page
// pages/dashboard.vue
@ dashboard page
此时访问 dashboard 页面,会跳转到登录页面。
Nuxt 通过definePageMeta中的validate属性在你想要验证的每个页面中提供路由验证。
validate属性接受route作为参数。
statusCode/statusMessage的对象,以立即响应错误(其他匹配将不会被检查)。如果用例比较复杂,可以使用匿名路由中间件。
// pages/posts/[id].vue
<template>
<div>
<h1>@ posts page #id {{ postId }}</h1>
</div>
</template>
<script setup>
definePageMeta({
validate: async (route) => {
// 检查ID是否由数字组成
return /^\d+$/.test(route.params.id);
},
});
const route = useRoute();
const postId = ref(0);
if (route) postId.value = route.params.id;
</script>
<style lang="scss" scoped></style>
此时访问路由 posts/1 页面正常显示,但访问 posts/abc 则会跳转到 404 页面。