Vue-router進階:導航守衛
全域性前置守衛
使用router.beforeEach註冊一個全域性前置守衛。
const router = new VueRouter({...}) router.beforeEach((to,from,next)=>{ //... })
當一個導航觸發時,全域性前置守衛按照建立順序呼叫。守衛是非同步解析執行,此時導航在所有守衛resolve完之前一直處於等待中。
每個守衛方法接收三個引數:
*to:Route即將要進入的目標路由物件。 *from:Route當前導航正要離開的路由。 *next:Function一定要呼叫該方法來resolve這個鉤子。執行效果依賴next方法的呼叫引數。 next():進行管道中的下一個鉤子。如果全部鉤子執行完了,則導航的狀態就是confirmed(確認的)。 next(false):中斷當前的導航。如果瀏覽器的URL改變了(可能是使用者手動或者瀏覽器後退按鈕),那麼URL地址會重置到from路由對應的地址。 next('/')或者({path:'/'}):跳轉到一個不同的地址。當前的導航被中斷,然後進行一個新的導航。你可以向next傳遞任意位置物件,且允許設定諸如replace:true、name:'home'之類的選項以及任何用在router-link的to prop或router.push中的選項。 next(error):如果傳入next的引數是一個Error例項,則導航會被終止且該錯誤會被傳遞給router.onError()註冊過的回撥。
確保要呼叫next方法,否則鉤子就不會被resolved。
全域性解析首位
2.5.0新增:你可以用router.beforeResolve註冊一個全域性守衛。這和router.beforeEach類似,區別是在導航被確認之前,同時在所有元件內守衛和非同步路由元件被解析之後,解析守衛就被呼叫。
全域性後置鉤子
和守衛不同的是,這些鉤子不會接受 next 函式也不會改變導航本。
router.afterEach((to,from)=>{ //... })
路由獨享的守衛
你可以在路由配置上直接定義beforeEnter守衛:
const router = new VueRouter({ routes:[ path:'/foo', component:Foo, beforeEnter:(to,from,next)=>{ //... } ] }) //這些守衛與全域性前置守衛的方法引數是一樣的。
組建內的守衛
最後,可以在路由元件內直接定義以下路由導航守衛:
*beforeRouterEnter *beforeRouterUpdate *beforeRouterLeave
const Foo = { template:`...`, beforeRouteEnter(to,from,next){ //在渲染元件的對應路由被confirm前呼叫。 //不能獲取元件例項this //因為當守衛執行前,元件例項還沒被建立。 }, beforeRouteUpdate(to,from,next){ //在當前路由改變,但是該元件被複用時呼叫。 //舉例來說,對於一個帶有動態引數路徑/foo/:id,在/foo/1和/foo/2之間跳轉的時候。 //由於會渲染同樣的Foo元件,因此元件例項會被複用。而這個鉤子就會在這個情況下被呼叫。 //可以訪問元件例項this }, beforeRouteLeave(to,from,next){ //導航離開該元件的對應路由時呼叫。 //可以訪問元件例項this } }
beforeRouteEnter守衛不能訪問this,因為守衛在導航確認前被呼叫,因此即將登場的新元件還沒被建立。不過可以通過傳一個回撥函式next來訪問組建例項。在導航被確認的時候執行回撥,並且把元件例項作為回撥方法的引數。
beforeRouteEnter(to,from,next){ next(vm=>{ //通過vm訪問元件例項。 }) }
注意beforeRouteEnter是支援next傳遞迴調的唯一守衛。對於beforeRouteEnter和beforeRouteLeave來說,this已經可用了,所以不支援傳遞迴調,因為沒有必要了。
beforeRouteUpdate(to,from,next){ this.name = to.params.name; next(); }
這個離開守衛通常用來禁止使用者在還未儲存修改前突然離開。該導航可以通過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) } }
完整的導航解析流程
1.導航被觸發。
2.在失活的元件裡呼叫離開守衛。
3.呼叫全域性的 beforeEach 守衛。
4.在重用的元件裡呼叫 beforeRouteUpdate 守衛 (2.2+)。
5.在路由配置裡呼叫 beforeEnter。
6.解析非同步路由元件。
7.在被啟用的元件裡呼叫 beforeRouteEnter。
8.呼叫全域性的 beforeResolve 守衛 (2.5+)。
9.導航被確認。
10.呼叫全域性的 afterEach 鉤子。
11.觸發 DOM 更新。
12.用建立好的例項呼叫 beforeRouteEnter 守衛中傳給 next 的回撥函式。**