middleware
Nuxt 提供一个可自定义的 路由中间件 框架,您可以在整个应用程序中使用,适合提取您希望在导航到特定路由之前运行的代码。
有三种类型的路由中间件:
- 匿名(或内联)路由中间件直接在页面内定义。
- 命名路由中间件,放置在
middleware/
中,当在页面上使用时,通过异步导入自动加载。 - 全局路由中间件,放置在
middleware/
中并带有.global
后缀,在每次路由更改时运行。
头两种类型的路由中间件可以在 definePageMeta
中定义。
myMiddleware
变为 my-middleware
。使用
路由中间件是接受当前路由和下一个路由作为参数的导航守卫。
export default defineNuxtRouteMiddleware((to, from) => {
if (to.params.id === '1') {
return abortNavigation()
}
// 在真实应用中,您可能不会将每个路由重定向到 `/`
// 但在重定向之前检查 `to.path` 是重要的,否则你
// 可能会得到一个无限重定向循环
if (to.path !== '/') {
return navigateTo('/')
}
})
Nuxt 提供两个可以从中间件直接返回的全局可用助手。
navigateTo
- 重定向到给定路由abortNavigation
- 中止导航,并可选提供错误消息。
与 vue-router
中的 导航守卫 不同,不会传递第三个 next()
参数,并且 重定向或路由取消通过从中间件返回值来处理。
可能的返回值有:
- 什么也不返回(一个简单的
return
或根本不返回) - 不会阻止导航,将移动到下一个中间件函数(如果有)或完成路由导航 return navigateTo('/')
- 重定向到给定路径,如果重定向发生在服务器端,将重定向代码设置为302
Foundreturn navigateTo('/', { redirectCode: 301 })
- 重定向到给定路径,如果重定向发生在服务器端,将重定向代码设置为301
Moved Permanentlyreturn abortNavigation()
- 停止当前导航return abortNavigation(error)
- 以错误拒绝当前导航
中间件顺序
中间件按以下顺序运行:
- 全局中间件
- 页面定义的中间件顺序(如果有多个使用数组语法声明的中间件)
例如,假设您有以下中间件和组件:
-| middleware/
---| analytics.global.ts
---| setup.global.ts
---| auth.ts
<script setup lang="ts">
definePageMeta({
middleware: [
function (to, from) {
// 自定义内联中间件
},
'auth',
],
});
</script>
您可以期待中间件按如下顺序运行:
analytics.global.ts
setup.global.ts
- 自定义内联中间件
auth.ts
全局中间件排序
默认情况下,全球中间件按文件名的字母顺序执行。
但是,有时您希望定义一个特定的顺序。例如,在最后一个场景中,setup.global.ts
可能需要在 analytics.global.ts
之前运行。在这种情况下,我们建议用“字母”编号为全局中间件加前缀。
-| middleware/
---| 01.setup.global.ts
---| 02.analytics.global.ts
---| auth.ts
10.new.global.ts
将出现在 2.new.global.ts
之前。这就是为什么示例中的前缀是单个数字的 0
。中间件运行时机
如果您的网站是服务器渲染或生成的,初始页面的中间件将在页面渲染时和客户端上再次执行。如果您的中间件需要浏览器环境,比如如果您有生成的网站、积极缓存响应,或者想从本地存储读取值时,这可能是必要的。
但是,如果您想避免这种行为,您可以这样做:
export default defineNuxtRouteMiddleware(to => {
// 在服务器上跳过中间件
if (import.meta.server) return
// 在客户端跳过中间件
if (import.meta.client) return
// 或者仅在客户端初始化加载时跳过中间件
const nuxtApp = useNuxtApp()
if (import.meta.client && nuxtApp.isHydrating && nuxtApp.payload.serverRendered) return
})
This is true even if you throw an error in your middleware on the server, and an error page is rendered. The middleware will still run again in the browser.
useError
来检查是否正在处理错误。动态添加中间件
可以通过 addRouteMiddleware()
助手函数手动添加全局或命名路由中间件,例如在插件内。
export default defineNuxtPlugin(() => {
addRouteMiddleware('global-test', () => {
console.log('这个全局中间件是在插件中添加的,并将在每次路由更改时运行')
}, { global: true })
addRouteMiddleware('named-test', () => {
console.log('这个命名中间件是在插件中添加的,并将覆盖任何同名的现有中间件')
})
})
示例
-| middleware/
---| auth.ts
在您的页面文件中,您可以引用此路由中间件:
<script setup lang="ts">
definePageMeta({
middleware: ["auth"]
// 或 middleware: 'auth'
})
</script>
现在,在导航到该页面完成之前,将运行 auth
路由中间件。
在构建时设置中间件
您可以在 pages:extend
钩子中添加命名路由中间件,而不是在每个页面上使用 definePageMeta
。
import type { NuxtPage } from 'nuxt/schema'
export default defineNuxtConfig({
hooks: {
'pages:extend' (pages) {
function setMiddleware (pages: NuxtPage[]) {
for (const page of pages) {
if (/*某个条件*/ true) {
page.meta ||= {}
// 请注意,这将覆盖页面中 `definePageMeta` 中设置的任何中间件
page.meta.middleware = ['named']
}
if (page.children) {
setMiddleware(page.children)
}
}
}
setMiddleware(pages)
}
}
})