Middleware 就像是你進入一個地方時的入口一樣,可以在存取每個頁面之前執行特定的操作,比如驗證身份、處理資料等,讓我們能夠有效管理應用程式的行為。
首先確認 app.vue
有 <NuxtPage />
元件。
// app.vue
<template>
<NuxtPage />
</template>
在頁面中透過 definePageMeta
的 middleware
設定。
建立頁面
pages
┣ user.vue 要加入 middleware 的頁面
┗ unAuthorized.vue 不符合條件時導向的頁面
// pages/user.vue
<template>
<h1>I'm {{ $route.query.id }}</h1>
</template>
// pages/unAuthorized.vue
<template>
<h1>WHO ARE YOU</h1>
</template>
在進到 /user
之前,確認 url 要有 id 可以識別身分,如果沒有則導向未授權頁面。
// pages/user.vue
<script setup lang="ts">
definePageMeta({
middleware: [
function (to, from) {
if (to.query.id === undefined) {
return navigateTo('/UnAuthorized')
}
},
],
});
</script>
執行結果:/user
沒有 id 時,route 會自動導向 /UnAuthorized
。
檔案建立在 middleware/
,在頁面中透過 definePageMeta
設定。middleware
名稱為檔案名稱的 kebab-case。
在專案目錄底下建立 middleware/
資料夾,再建立 checkAuth.ts
檔案。
nuxt-project
┣ middleware
┃ ┗ checkAuth.ts
在 /middleware/checkAuth.ts
加入以下程式碼。
// middleware/checkAuth.ts
export default defineNuxtRouteMiddleware((to, from) => {
console.log("middleware in checkAuth.ts");
//此處加上 middleware 要執行的動作。
});
在須執行此 Middleware 的頁面(範例檔案為接續「匿名」的 /pages/user.vue
)。
// pages/user.vue
<script setup lang="ts">
definePageMeta({
middleware: [
function (to, from) {
console.log("middleware in user.vue");
if (to.query.id === undefined) {
return navigateTo("/UnAuthorized");
}
},
"check-auth",
],
});
</script>
執行結果,請求 http://127.0.0.1:3000/user?id=1234
時,會執行「匿名」及「具名」的 Middleware。
在 middleware/
建立檔案設定,名稱須加上 .global
以識別是全域的。
當路徑改變時,都會自動去執行全域的 middleware
。
建立 checkRoute.global.ts
檔案
nuxt-project
┣ middleware
┃ ┣ checkAuth.ts
┃ ┗ checkRoute.global.ts
加入以下程式碼
// middleware/checkRoute.global.ts
export default defineNuxtRouteMiddleware((to, from) => {
console.log("middleware in checkRoute.global.ts");
//此處加上全域 middleware 要執行的動作。
});
執行結果:存取 http://127.0.0.1:3000/user?id=1234
時,會執行「全域」、「匿名」及「具名」的 Middleware,且「全域」會先被執行。
to
(去哪裡) 跟 from
(從哪來)提供的參數相同。
下方為請求 http://127.0.0.1:3000/user?id=1234
,console.log(to)
的範例。
值得注意的是 params
代表的是路由:/user/[id]
;而 query
代表的是路由:user?id=[id]
。
abortNavigation (err?: string | Error)
:不允許進到此頁面(錯誤代碼 500),參數為錯誤訊息。
// pages/user.vue
script setup lang="ts">
efinePageMeta({
middleware: [
function (to, from) {
abortNavigation("沒權限");
},
],
);
/script>
navigateTo (to: RouteLocationRaw | undefined | null, options?: { replace: boolean, redirectCode: number, external: boolean )
:導向其他畫面,參數可指定 url 及其他控制變數。
此範例為上面「匿名」範例
「全域」的一定最優先,且「全域」之間的優先順序是依照檔名。
「匿名」及「具名」則是依據在 definePageMeta
設定的順序決定。
// 可以在全域的檔名前面加上數字來設定先後順序
middleware
┣ 01.checkRoute.global.ts
┣ 02.analytics.global.ts
┣ checkAuth.ts
Middleware 可以根據不同處理程序(例如伺服器端和客戶端)控制在特定流程時選擇性跳過。
export default defineNuxtRouteMiddleware(to => {
// server 不執行
if (process.server) return
// client 不執行
if (process.client) return
// client 首次渲染時不執行(重新 reload 頁面也算是首次渲染)
const nuxtApp = useNuxtApp()
if (process.client && nuxtApp.isHydrating && nuxtApp.payload.serverRendered) return
})
今天介紹了 Pages 的 Middleware,明天會介紹 Nuxt 3 Server API 的使用方法,而 Server API 也有 Middleware,兩者有什麼不一樣呢?明日揭曉!