中介層
Nuxt 提供中介層,以便在導航至特定路由之前執行程式碼。
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()
參數,而且**重新導向或路由取消由從中介層傳回值來處理**。
可能的傳回值為
- nothing(簡單的
return
或根本沒有傳回值)- 不會阻止導航,而且會移至下一個中介層函式(如果有的話),或者完成路由導航 return navigateTo('/')
- 重新導向至給定的路徑,而且如果重新導向發生在伺服器端,則會將重新導向代碼設定為302
找到return navigateTo('/', { redirectCode: 301 })
- 重新導向至給定的路徑,而且如果重新導向發生在伺服器端,則會將重新導向代碼設定為301
永久移動return 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
路由中介軟體。
在 Docs > Examples > Routing > Middleware 中閱讀並編輯即時範例。
在建置時設定中介軟體
您可以在 pages:extend
hook 中新增具名的路由中介軟體,而不是在每個頁面上使用 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)
}
}
})