"導航" 表示路由正在發生改變vue
vue-router
提供的導航守衛主要用來經過跳轉或取消的方式守衛導航。有多種機會植入路由導航過程當中,他們分爲三種:git
注:參數或查詢的改變並不會觸發進入/離開的導航守衛 (你能夠經過觀察 $route
對象來應對這些變化,或使用 beforeRouteUpdate
的組件內守衛。)vue-router
給一張圖直觀的看一下:
瀏覽器
可使用 router.beforeEach
註冊一個全局前置守衛bash
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('/')
或者 next({ path: '/' })
: 跳轉到一個不一樣的地址。當前的導航被中斷,而後進行一個新的導航。你能夠向 next
傳遞任意位置對象,且容許設置諸如 replace: true
、name: 'home'
之類的選項以及任何用在 router-link
的 to prop
或 router.push
中的選項。next(error)
: (2.4.0+) 若是傳入 next
的參數是一個 Error 實例,則導航會被終止且該錯誤會被傳遞給 router.onError()
註冊過的回調。確保要調用next
方法,不然鉤子就不會被resolvedui
能夠用router.beforeResolve
註冊一個全局守衛。這和 router.beforeEach
相似,區別是在導航被確認以前,同時在全部組件內守衛和異步路由組件被解析以後,解析守衛就被調用。this
能夠註冊一個全局後置鉤子,然而和守衛不一樣的是,這些鉤子不會接受next
函數也不會改變導航自己spa
router.afterEach((to, from) => {
// ...
})
複製代碼
能夠在路由配置上直接定義 beforeEnter
守衛:
const router = new VueRouter({
routes: [
{
path: '/foo',
component: Foo,
beforeEnter: (to, from, next) => {
// ...
}
}
]
})
複製代碼
這些守衛與全局前置守衛的方法參數是同樣的。
固然,也能夠在路由組件內直接定義如下路由導航守衛:
beforeRouteEnter
beforeRouteUpdate
beforeRouteLeave
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
傳遞迴調的惟一守衛。對於 beforeRouteUpdate
和 beforeRouteLeave
來講,this
已經可用了,因此不支持傳遞迴調,由於沒有必要了。
beforeRouteUpdate (to, from, next) {
// just use `this`
this.name = to.params.name
next()
}
複製代碼
beforeRouteUpdate
是在路徑發生改變時調用
這個離開守衛一般用來禁止用戶在還未保存修改前忽然離開。該導航能夠經過 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
的回調函數。
//Router定義
Vue.use(Router)
const router = new Router({
...
})
//導航守衛
router.beforeEach((to, from, next) => {
console.log("導航前置守衛: beforeEach,");
next();
})
router.afterEach((to, from) => {
console.log("導航後置守衛: afterEach,");
})
router.beforeResolve ((to, from, next) => {
console.log("導航解析守衛: beforeResolve,");
next();
})
複製代碼
組件鉤子:
export default {
//鉤子
beforeCreate(){
console.log("組件鉤子: beforeCreate");
},
created(){
console.log("組件鉤子: created");
},
beforeMount(){
console.log("組件鉤子: beforeMount");
},
mounted(){
console.log("組件鉤子: mounted");
},
beforeUpdate(){
console.log("組件鉤子: beforeUpdate");
},
updated(){
console.log("組件鉤子: updated");
},
beforeDestroy(){
console.log("組件鉤子: beforeDestroy");
},
destoryed(){
console.log("組件鉤子: destoryed");
},
beforeRouteEnter (to, from, next) {
console.log("組件內部守衛: beforeRouteEnter,");
next()
},
beforeRouteUpdate (to, from, next) {
console.log("組件內部守衛: beforeRouteUpdate,");
next()
},
beforeRouteLeave (to, from, next) {
console.log("組件內部守衛: beforeRouteLeave,");
next()
}
}
複製代碼
執行輸出順序:
導航前置守衛: beforeEach
組件內部守衛: beforeRouteEnter
導航解析守衛: beforeResolve
導航後置守衛: afterEach
組件鉤子: beforeCreate
組件鉤子: created
組件鉤子: beforeMount
組件鉤子: mounted
//執行跳轉
組件內部守衛: beforeRouteLeave
導航前置守衛: beforeEach
導航解析守衛: beforeResolve
導航後置守衛: afterEach
組件鉤子: beforeDestroy
複製代碼
關於 Vue組件 的生命週期與鉤子函數,請參考個人文章《Vue 生命週期與鉤子函數》