vue路由——進階篇(一)
在vue路由的基礎篇中,我們主要講解了如何使用路由。那麼進階篇我們主要去了解一下路由守衛等知識。
路由守衛
vue-router 提供的路由守衛主要用於**通過跳轉或取消的方式守衛導航,或者新增許可權驗證、資料獲取等業務邏輯。**路由守衛主要分為:全域性守衛、路由獨享的守衛和元件內守衛
每一個導航守衛都有三個引數:to
、from
、next
,除了router.afterEach()
方法之外。解析三個引數:
to: Route
: 即將要進入的目標路由物件from: Route
: 當前導航正要離開的路由next: Function
:一定要呼叫該方法來 resolve 這個鉤子。- next():進行管道中的下一個鉤子。如果全部鉤子執行完了,則導航的狀態就是 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 的引數是一個 Error 例項,則導航會被終止且該錯誤會被傳遞給 router.onError() 註冊過的回撥。
全域性守衛
這篇我們主要去了解一下全域性守衛。全域性守衛是用在全域性的,專案中的任何路由和元件都能經過去全域性守衛。全域性守衛分為:全域性前置守衛、全域性解析守衛和全域性後置鉤子。
全域性前置守衛,是用在導航觸發時,是全域性守衛中最先被觸發的守衛,是路由守衛中第二個被觸發的守衛,可以通過router.beforeEach()
方法註冊前置守衛 。當存在多個前置守衛時,全域性前置守衛按照建立順序呼叫。
router.beforeEach((to, from, next) => {
console.log("這個是我要進入的路由物件", to);
console. log("這個是我要離開的路由物件", from);
if (to.path == '/books') {
next();
} else {
next('/books');
}
})
全域性解析守衛,使用router.beforeResolve()
註冊。和全域性前置守衛類似,在導航確認之前,在所有元件內守衛和非同步路由元件被解析之後,解析守衛被呼叫。簡單來說,**這個全域性守衛在元件內守衛和路由獨享守衛全部呼叫之後呼叫,但在全域性後置鉤子守衛之前呼叫。**它的使用方法和router.beforeEach()
方法一樣。
全域性後置鉤子,使用router.afterEach()
方法註冊。它與守衛不同,它沒有第三個引數,也不會改變導航。
路由獨享的守衛
路由獨享的守衛,是在 Router 構建選項routes
選項中配置的,使用beforeEnter
選項直接定義。它只在該定義它的元件上生效,在全域性前置守衛被呼叫之後,在進入路由元件之前呼叫。 毫無疑問它的使用方法和全域性前置守衛一樣。
{
path: '/',
component: Index,
beforeEnter: (to, from, next) => {
console.log("我進入了首頁的路由獨享的守衛");
next();
}
}
元件內守衛
元件內守衛有三個,分別是beforeRouteEnter
、beforeRouteUpdate
、beforeRouteLeave
。它們的使用方法,和呼叫時機如下:
const Foo = {
template: `...`,
beforeRouteEnter (to, from, next) {
// 在渲染該元件的對應路由被 confirm 前呼叫
// 不!能!獲取元件例項 `this`
// 因為當守衛執行前,元件例項還沒被建立
next();
},
beforeRouteUpdate (to, from, next) {
// 在當前路由改變,但是該元件被複用時呼叫
// 舉例來說,對於一個帶有動態引數的路徑 /foo/:id,在 /foo/1 和 /foo/2 之間跳轉的時候,
// 由於會渲染同樣的 Foo 元件,因此元件例項會被複用。而這個鉤子就會在這個情況下被呼叫。
// 可以訪問元件例項 `this`
next();
},
beforeRouteLeave (to, from, next) {
// 導航離開該元件的對應路由時呼叫
// 可以訪問元件例項 `this`
next();
}
}
在元件內守衛中最特殊的是beforeRouteEnter
守衛,這個守衛是所有守衛中唯一一個支援回撥函式的守衛。這個守衛在導航被確認的時候執行回撥,並且把元件例項作為回撥方法的引數。
beforeRouteEnter (to, from, next) {
next(vm => {
// 通過 `vm` 訪問元件例項
})
}
在上面例項中,我們闡述了,元件內的三種守衛。beforeRouteEnter
守衛當元件被渲染的時候被呼叫,beforeRouteLeave
守衛當離開改元件(頁面上不顯示該元件)時呼叫,beforeRouteUpdate
守衛當元件重新渲染時呼叫。
完整的導航解析流程
當從一個URL切換到另外一個URL時,所有守衛執行的流程。
- 第一步:觸發導航;
- 第二步:從原先的URL離開,表明改頁面的元件全部被銷燬,所以元件內守衛
beforeRouteLeave
被呼叫; - 第三步:進入新的 URL 地址,則全域性前置守衛
beforeEach
被呼叫; - 第四步:如果修改後的 URL 地址,也複用了原先 URL 地址的元件,則呼叫該元件的元件內守衛
beforeRouteUpdate
。如果沒有複用則這步忽略; - 第五步:對路由進行匹配,在匹配到正確的路由之後,呼叫路由獨享的守衛
beforeEnter
; - 第六步:解析非同步路由元件;
- 第七步:呼叫元件內守衛
beforeRouteEnter
; - 第八步:呼叫全域性解析守衛
beforeResolve
; - 第九步:導航被確認。
- 第十步:呼叫全域性後置鉤子
afterEach
; - 第十一步:觸發 DOM 更新;
- 第十二步:在完成以上過程之後,呼叫 元件內守衛
beforeRouteEnter
中傳給 next 的回撥函式,建立好的元件例項會作為回撥函式的引數傳入。