之前有預告過,發送 API 的時機點需視不同情境及 UX 體驗規劃而定,因此除了選擇在元件內的生命週期 created
發送,另外在 Vue Router 還有像警衛一般的「導航守衛(Navigation Guards)」,分別可以駐守在全域、路由和元件內。
在導航守衛文件的最底部,已先整理出 Resolution Flow 讓我們知道3種守衛位置、7個守衛時機的先後順序,以便根據專案需求在合適的時間點發送 API 或執行其他動作。
(圖片來源:Vue Router - Navigation Guards - The Full Navigation Resolution Flow)
三種守衛位置分別在趨近目標路由的過程中慢慢收斂守衛範圍,由大至小分別是在全域、路由、元件內調用。
to
:即將進入的目標路由from
:準備離開的上個路由next
(必選):繼續執行的 callback 函式,必須呼叫 next()
才會執行下一步;因此在所有導航守衛中為必選程序,在同一個導航守衛中可使用一或多次beforeEach
:進入每個路由之前
beforeResolve
:在路由完成跳轉之前,但所有元件內守衛和路由元件已完成解析
afterEach
:每個路由完成跳轉之後
應用範例:登入系統需要驗證會員身份,部分路徑內容會根據使用者身份限制瀏覽範圍或操作行為,例如成為正式會員之後才能在網站內進行購買商品。因此會選擇在全域 beforeEach
進入每一個路由之前就先判斷會員目前的狀態,若該路徑僅限於會員才能進入,就會將使用者導向登入頁面,引導使用者註冊為會員。
routes 中的每個路由物件稱為 route record,通常會搭配設置 Route Meta 限制個別路由的權限,並在每次進入路由之前先判斷 route record 所設置的 meta
狀態,再做接下來的導向流程。
const router = new VueRouter({
routes: [
{
path: "/member",
redirect: { name: "Profile" },
component: MemberPage,
children: [
{
path: "collection",
name: "Collection",
component: Collection,
},
{
path: "collection/purchase/:bookName",
name: "Purchase",
component: Purchase,
meta: { requiresAuth: true } // 設為需為登入狀態
},
],
}
]
})
// 全域設置進入路由之前的時間點
router.beforeEach((to, from, next) => {
// 當路由物件的 meta 設有 requiresAuth 時
if (to.matched.some(record => record.meta.requiresAuth)) {
// 尚未登入
if (!Token) {
next({ path: '/login' }) // 導向登入頁面
} else {
next() // 登入成功,則可繼續往下執行
}
} else {
next() // 確保一定要使用 next()
}
})
beforeEnter
:準備進入單一路由之前beforeEnter
,不會影響到其他路由。beforeRouteEnter
:路由進入元件之前beforeRouteUpdate
:具有相同元件的路由發生更新時beforeRouteLeave
:路由離開元件之前beforeRouteUpdate
發送 API 即時接收資料,才能在路由切換之後重新接收資料並渲染至畫面上。