文章目录
- 路由 Routing
- 页面 Pages
- 导航 Navigation
- 路由参数 Route Parameters
- 路由中间件 Route Middleware
- 路由验证 Route Validation
Nuxt 官网地址: https://nuxt.com/
路由 Routing
Nuxt 的一个核心功能是文件系统路由器。pages/
目录下的每个 Vue 文件都会创建一个相应的 URL(或路由)来显示该文件的内容。通过为每个页面使用动态导入,Nuxt 利用代码拆分为所请求的路由提供最少的 JavaScript。
页面 Pages
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
<template>
<div>
<h1>@ posts page</h1>
</div>
</template>
<style lang="scss" scoped></style>
导航 Navigation
<NuxtLink>
组件在页面之间建立链接。它渲染了一个<a>
标签,其 href 属性被设置为页面的路径。一旦应用程序水合,页面转换将通过更新浏览器 URL 在 JavaScript 中执行。这可以防止全页面刷新,并允许动画过渡。
当进入客户端视口时,Nuxt 将自动提前预取组件和链接页面的有效载荷(生成的页面),从而加快导航速度。
下面的代码示例,是在默认布局文件中:
// layouts/default.vue
<template>
<header>
<nav>
<ul>
<li><NuxtLink to="/">Home</NuxtLink></li>
<li><NuxtLink to="/dashboard">Dashboard</NuxtLink></li>
<li><NuxtLink to="/about">About</NuxtLink></li>
<li><NuxtLink to="/posts/1">Post 1</NuxtLink></li>
<li><NuxtLink to="/posts/2">Post 2</NuxtLink></li>
</ul>
</nav>
</header>
</template>
此时可以点击页面顶部的导航切换页面了。
路由参数 Route Parameters
在<script setup>
块或 Vue 组件的setup()
方法,通过组合函数useRoute()
以访问当前路由的详细信息。
正好,可以在 pages/posts/[id].vue 文件中来实践一下:
// pages/posts/[id].vue
<template>
<div>
<h1>@ posts page #id {{ route.params.id }}</h1>
</div>
</template>
<script setup>
const route = useRoute();
</script>
<style lang="scss" scoped></style>
此时,点击页面顶部的导航链接就可以看到效果了。
路由中间件 Route Middleware
Nuxt 提供了一个可定制的路由中间件框架,您可以在整个应用程序中使用,非常适合在导航到特定路由之前提取您想要运行的代码。
路由中间件运行于 Nuxt 应用程序的 Vue 部分。尽管名称相似,但它们与服务器中间件完全不同,后者运行于应用程序的 Nitro 服务器部分。
路由中间件有三种:
- 匿名(或内联)路由中间件(Anonymous route middleware):直接定义在使用路由中间件的页面中。
- 命名路由中间件(Named route middleware):放置在
middleware/
目录中,当在页面中使用时将通过异步导入自动加载。(注意:路由中间件的名称被规范化为kebab-case 横线命名法
,因此someMiddleware
变成了some-middleware
。) - 全局路由中间件(Global route 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;
};
- 然后,创建 login 页面
// pages/login.vue
<template>
<div>
<h1>@ login page</h1>
</div>
</template>
<script setup></script>
<style lang="scss" scoped></style>
- 最后,创建 dashboard 页面,并使用中间件
// pages/dashboard.vue
<template>
<div>
<h1>@ dashboard page</h1>
</div>
</template>
<script setup>
definePageMeta({
middleware: "auth",
});
</script>
<style lang="scss" scoped></style>
此时访问 dashboard 页面,会跳转到登录页面。
路由验证 Route Validation
Nuxt 通过definePageMeta
中的validate
属性在你想要验证的每个页面中提供路由验证。
validate
属性接受route
作为参数。
- 你可以返回一个布尔值,来确定这是否是一个有效的路由,并与此页面一起呈现。如果返回 false,并且找不到其他匹配的路由,则会导致 404 错误。
- 也可以直接返回一个带有
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 页面。