導航守衛 (Navigation Guards)
想像你的應用程式是一棟大樓,有些房間(路由)是對公眾開放的(首頁、關於我們),但有些房間是需要刷卡才能進入的(會員中心、後台管理)。
Vue Router 的 導航守衛 就是這些門禁系統。它們可以在路由跳轉發生 之前、解析時 或 之後 進行攔截。
一、 全域前置守衛 (Global Before Guards)
這是最常見的一種,通常用來檢查使用者是否已登入。
它掛在 router 實體上,對 所有 路由都有效。
javascript
// router/index.js
router.beforeEach((to, from) => {
// to: 即將要去的路由物件
// from: 當前正要離開的路由物件
// 1. 檢查該路由是否需要登入權限
if (to.meta.requiresAuth && !isAuthenticated()) {
// 2. 如果沒登入,重導向到登入頁
// 並帶上 redirect 參數,讓使用者登入後能跳回來
return {
path: "/login",
query: { redirect: to.fullPath },
};
}
// 3. 回傳 undefined 或 true 代表放行
});TIP
不再需要 next(): 在 Vue Router 3 中,我們必須呼叫 next()。雖然 v4 為了相容性還保留了它,但官方強烈建議直接 return 路由或 false 來控制流程。
二、 路由獨享守衛 (Per-Route Guards)
如果你只想對特定路由做檢查,可以直接寫在 routes 配置裡。
javascript
const routes = [
{
path: "/dashboard",
component: Dashboard,
beforeEnter: (to, from) => {
// 只有進入 /dashboard 時才會觸發
if (!isAdmin()) return "/error";
},
},
];三、 組件內守衛 (In-Component Guards)
這是定義在 .vue 檔案裡的。最常用的是 onBeforeRouteLeave。
1. 防止誤觸離開 (Dirty Form Check)
當使用者填寫表單到一半,不小心按了上一頁,我們希望能跳出警告。
html
<script setup>
import { onBeforeRouteLeave, onBeforeRouteUpdate } from "vue-router";
// 離開守衛
onBeforeRouteLeave((to, from) => {
if (formIsDirty.value) {
const answer = window.confirm("你有未儲存的變更,確定要離開嗎?");
// 如果使用者按取消,則回傳 false (阻止跳轉)
if (!answer) return false;
}
});
// 更新守衛 (當參數改變但組件重用時)
onBeforeRouteUpdate((to, from) => {
// id 變了,重抓資料
fetchData(to.params.id);
});
</script>四、 完整的解析流程 (The Full Flow)
這是一個常見的面試題:當你點擊一個連結時,守衛觸發的順序是什麼?
- 導航被觸發。
- 在失活的組件裡呼叫
beforeRouteLeave。 - 呼叫全域的
beforeEach守衛。 - 在重用的組件裡呼叫
beforeRouteUpdate。 - 在路由配置裡呼叫
beforeEnter。 - 解析非同步路由組件。
- 在被激活的組件裡呼叫
beforeRouteEnter。 - 呼叫全域的
beforeResolve守衛。 - 導航被確認。
- 呼叫全域的
afterEach鉤子 (這時已無法改變導航)。 - 觸發 DOM 更新。
- 呼叫
beforeRouteEnter守衛中傳給next的回調函數。
總結
beforeEach: 用於全域權限檢查 (Auth)。beforeEnter: 針對特定路由的檢查 (Admin)。onBeforeRouteLeave: 防止資料遺失 (Form)。onBeforeRouteUpdate: 響應參數變化 (Params)。
下一章,我們將直接跳過 07 (轉場) 與 08 (KeepAlive),因為我們之前已經先行完成了這最困難的兩章!所以我們將進入最後的優化環節:路由懶加載。