middleware
Nuxt 提供中介層 (middleware) 以在導航至特定路由之前執行程式碼。
Nuxt 提供可自訂的路由中介層框架,您可以在整個應用程式中使用它,非常適合提取您想要在導航至特定路由之前執行的程式碼。
有三種路由中介層
- 匿名(或內聯)路由中介層直接在頁面中定義。
- 具名路由中介層,放置在
middleware/
中,並在頁面上使用時透過異步導入自動載入。 - 全域路由中介層,放置在
middleware/
中,並帶有.global
後綴,並在每次路由變更時執行。
前兩種路由中介層可以在 definePageMeta
中定義。
中介層的名稱會正規化為 kebab-case:
myMiddleware
變成 my-middleware
。路由中介層在 Nuxt 應用程式的 Vue 部分中執行。儘管名稱相似,它們與 伺服器中介層 完全不同,後者在應用程式的 Nitro 伺服器部分中執行。
用法
路由中介層是導航守衛,它接收當前路由和下一個路由作為參數。
middleware/my-middleware.ts
export default defineNuxtRouteMiddleware((to, from) => {
if (to.params.id === '1') {
return abortNavigation()
}
// In a real app you would probably not redirect every route to `/`
// however it is important to check `to.path` before redirecting or you
// might get an infinite redirect loop
if (to.path !== '/') {
return navigateTo('/')
}
})
Nuxt 提供了兩個全域可用的輔助函式,可以直接從中介層返回。
navigateTo
- 重定向到給定路由abortNavigation
- 中止導航,並帶有可選的錯誤訊息。
與 vue-router
中的導航守衛不同,不會傳遞第三個 next()
參數,且重新導向或路由取消由從中介層傳回值來處理。
可能的傳回值為
- 無任何返回值 (簡單的
return
或沒有 return) - 不會阻止導航,並將移動到下一個中介層函式(如果有的話),或完成路由導航 return navigateTo('/')
- 重新導向到給定路徑,如果重新導向發生在伺服器端,則會將重新導向代碼設定為302
Foundreturn navigateTo('/', { redirectCode: 301 })
- 重新導向到給定路徑,如果重新導向發生在伺服器端,則會將重新導向代碼設定為301
Moved Permanentlyreturn abortNavigation()
- 停止當前導航return abortNavigation(error)
- 拒絕當前導航並顯示錯誤
我們建議使用上面的輔助函式來執行重新導向或停止導航。vue-router 文件中描述的其他可能傳回值可能有效,但未來可能會發生重大變更。
中介層順序
中介層按以下順序執行
- 全域中介層
- 頁面定義的中介層順序(如果有多個使用陣列語法宣告的中介層)
例如,假設您有以下中介層和組件
middleware/ 目錄
-| middleware/
---| analytics.global.ts
---| setup.global.ts
---| auth.ts
pages/profile.vue
<script setup lang="ts">
definePageMeta({
middleware: [
function (to, from) {
// Custom inline middleware
},
'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
作為個位數數字的前綴。中介層何時執行
如果您的網站是伺服器渲染或生成的,則初始頁面的中介層將在頁面渲染時以及稍後在客戶端再次執行。如果您的中介層需要瀏覽器環境,例如您有生成的網站、積極快取響應,或想要從本機儲存空間讀取值,則可能需要這樣做。
但是,如果您想避免這種行為,您可以這樣做
middleware/example.ts
export default defineNuxtRouteMiddleware(to => {
// skip middleware on server
if (import.meta.server) return
// skip middleware on client side entirely
if (import.meta.client) return
// or only skip middleware on initial client load
const nuxtApp = useNuxtApp()
if (import.meta.client && nuxtApp.isHydrating && nuxtApp.payload.serverRendered) return
})
渲染錯誤頁面是一個完全獨立的頁面載入,這意味著任何已註冊的中介層都會再次執行。您可以使用中介層中的
useError
來檢查是否正在處理錯誤。動態新增中介層
可以使用 addRouteMiddleware()
輔助函式手動新增全域或具名路由中介層,例如從外掛程式中新增。
export default defineNuxtPlugin(() => {
addRouteMiddleware('global-test', () => {
console.log('this global middleware was added in a plugin and will be run on every route change')
}, { global: true })
addRouteMiddleware('named-test', () => {
console.log('this named middleware was added in a plugin and would override any existing middleware of the same name')
})
})
範例
目錄結構
-| middleware/
---| auth.ts
在您的頁面檔案中,您可以參考此路由中介層
<script setup lang="ts">
definePageMeta({
middleware: ["auth"]
// or middleware: 'auth'
})
</script>
現在,在完成導航到該頁面之前,將會執行 auth
路由中介層。
在 文件 > 範例 > 路由 > 中介層 中閱讀和編輯即時範例。
在建置時設定中介層
您可以於 pages:extend
鉤子中新增具名路由中介層,而無需在每個頁面上使用 definePageMeta
。
nuxt.config.ts
import type { NuxtPage } from 'nuxt/schema'
export default defineNuxtConfig({
hooks: {
'pages:extend' (pages) {
function setMiddleware (pages: NuxtPage[]) {
for (const page of pages) {
if (/* some condition */ true) {
page.meta ||= {}
// Note that this will override any middleware set in `definePageMeta` in the page
page.meta.middleware = ['named']
}
if (page.children) {
setMiddleware(page.children)
}
}
}
setMiddleware(pages)
}
}
})