導航守衛(wèi)有:1、全局前置守衛(wèi)“beforeEach”;2、全局解析守衛(wèi)“beforeResolve”;3、路由獨享的守衛(wèi)“beforeEnter”;4、組件內的守衛(wèi)“beforeRouteEnter”、“beforeRouteLeave”。
本教程操作環(huán)境:windows7系統(tǒng)、vue2.9.6版,DELL G3電腦。
vue-router 提供的導航守衛(wèi)主要用來通過跳轉或取消的方式守衛(wèi)導航。有多種機會植入路由導航過程中:全局的, 單個路由獨享的, 或者組件級的。
記住參數(shù)或查詢的改變并不會觸發(fā)進入/離開的導航守衛(wèi)。你可以通過觀察 $route 對象來應對這些變化,或使用 beforeRouteUpdate 的組件內守衛(wèi)。
全局前置守衛(wèi)
你可以使用 router.beforeEach 注冊一個全局前置守衛(wèi):
const router = new VueRouter({ ... }) router.beforeEach((to, from, next) => { // ... })
當一個導航觸發(fā)時,全局前置守衛(wèi)按照創(chuàng)建順序調用。守衛(wèi)是異步解析執(zhí)行,此時導航在所有守衛(wèi) resolve 完之前一直處于 等待中。
每個守衛(wèi)方法接收三個參數(shù):
-
to: Route: 即將要進入的目標 路由對象
-
from: Route: 當前導航正要離開的路由
-
next: Function: 一定要調用該方法來 resolve 這個鉤子。執(zhí)行效果依賴 next 方法的調用參數(shù)。
-
next(): 進行管道中的下一個鉤子。如果全部鉤子執(zhí)行完了,則導航的狀態(tài)就是 confirmed (確認的)。
-
next(false): 中斷當前的導航。如果瀏覽器的 URL 改變了 (可能是用戶手動或者瀏覽器后退按鈕),那么 URL 地址會重置到 from 路由對應的地址。
-
next('/') 或者 next({ path: '/' }): 跳轉到一個不同的地址。當前的導航被中斷,然后進行一個新的導航。你可以向 next 傳遞任意位置對象,且允許設置諸如 replace: true、name: 'home' 之類的選項以及任何用在 router-link 的 to prop 或 router.push 中的選項。
-
next(error): (2.4.0+) 如果傳入 next 的參數(shù)是一個 Error 實例,則導航會被終止且該錯誤會被傳遞給 router.onError() 注冊過的回調。
-
確保 next 函數(shù)在任何給定的導航守衛(wèi)中都被嚴格調用一次。它可以出現(xiàn)多于一次,但是只能在所有的邏輯路徑都不重疊的情況下,否則鉤子永遠都不會被解析或報錯。這里有一個在用戶未能驗證身份時重定向到 /login 的示例:
// BAD router.beforeEach((to, from, next) => { if (to.name !== 'Login' && !isAuthenticated) next({ name: 'Login' }) // 如果用戶未能驗證身份,則 `next` 會被調用兩次 next() }) // GOOD router.beforeEach((to, from, next) => { if (to.name !== 'Login' && !isAuthenticated) next({ name: 'Login' }) else next() })
全局解析守衛(wèi)
2.5.0 新增
在 2.5.0+ 你可以用 router.beforeResolve 注冊一個全局守衛(wèi)。這和 router.beforeEach 類似,區(qū)別是在導航被確認之前,同時在所有組件內守衛(wèi)和異步路由組件被解析之后,解析守衛(wèi)就被調用。
路由獨享的守衛(wèi)
你可以在路由配置上直接定義 beforeEnter 守衛(wèi):
const router = new VueRouter({ routes: [ { path: '/foo', component: Foo, beforeEnter: (to, from, next) => { // ... } } ] })
這些守衛(wèi)與全局前置守衛(wèi)的方法參數(shù)是一樣的。
組件內的守衛(wèi)
最后,你可以在路由組件內直接定義以下路由導航守衛(wèi):
-
beforeRouteEnter
-
beforeRouteUpdate (2.2 新增)
-
beforeRouteLeave
const Foo = { template: `...`, beforeRouteEnter(to, from, next) { // 在渲染該組件的對應路由被 confirm 前調用 // 不!能!獲取組件實例 `this` // 因為當守衛(wèi)執(zhí)行前,組件實例還沒被創(chuàng)建 }, beforeRouteUpdate(to, from, next) { // 在當前路由改變,但是該組件被復用時調用 // 舉例來說,對于一個帶有動態(tài)參數(shù)的路徑 /foo/:id,在 /foo/1 和 /foo/2 之間跳轉的時候, // 由于會渲染同樣的 Foo 組件,因此組件實例會被復用。而這個鉤子就會在這個情況下被調用。 // 可以訪問組件實例 `this` }, beforeRouteLeave(to, from, next) { // 導航離開該組件的對應路由時調用 // 可以訪問組件實例 `this` } }
beforeRouteEnter 守衛(wèi) 不能 訪問 this,因為守衛(wèi)在導航確認前被調用,因此即將登場的新組件還沒被創(chuàng)建。
不過,你可以通過傳一個回調給 next來訪問組件實例。在導航被確認的時候執(zhí)行回調,并且把組件實例作為回調方法的參數(shù)。
beforeRouteEnter (to, from, next) { next(vm => { // 通過 `vm` 訪問組件實例 }) }
注意 beforeRouteEnter 是支持給 next 傳遞回調的唯一守衛(wèi)。對于 beforeRouteUpdate 和 beforeRouteLeave 來說,this 已經(jīng)可用了,所以不支持傳遞回調,因為沒有必要了。
beforeRouteUpdate (to, from, next) { // just use `this` this.name = to.params.name next() }
這個離開守衛(wèi)通常用來禁止用戶在還未保存修改前突然離開。該導航可以通過 next(false) 來取消。
beforeRouteLeave (to, from, next) { const answer = window.confirm('Do you really want to leave? you have unsaved changes!') if (answer) { next() } else { next(false) } }
完整的導航解析流程
-
導航被觸發(fā)。
-
在失活的組件里調用 beforeRouteLeave 守衛(wèi)。
-
調用全局的 beforeEach 守衛(wèi)。
-
在重用的組件里調用 beforeRouteUpdate 守衛(wèi) (2.2+)。
-
在路由配置里調用 beforeEnter。
-
解析異步路由組件。
-
在被激活的組件里調用 beforeRouteEnter。
-
調用全局的 beforeResolve 守衛(wèi) (2.5+)。
-
導航被確認。
-
調用全局的 afterEach 鉤子。
-
觸發(fā) DOM 更新。
-
調用 beforeRouteEnter 守衛(wèi)中傳給 next 的回調函數(shù),創(chuàng)建好的組件實例會作為回調函數(shù)的參數(shù)傳入。
【