??什么是導(dǎo)航守衛(wèi)?顧名思義,導(dǎo)航守衛(wèi)的意思就是監(jiān)聽每一個(gè)路由跳轉(zhuǎn)的過程,然后提供一些鉤子函數(shù)讓你有機(jī)會(huì)在跳轉(zhuǎn)的過程中植入相關(guān)信息
1.導(dǎo)航守衛(wèi)的分類
?? ①:全局守衛(wèi)(全局前置守衛(wèi)、全局解析守衛(wèi)、全局后置鉤子)
?? ②:路由守衛(wèi)(路由獨(dú)享守衛(wèi))
?? ③:組件內(nèi)守衛(wèi)(加載、更新、離開)
2.全局守衛(wèi)
??(1):全局前置守衛(wèi)router.beforeEach
????當(dāng)一個(gè)導(dǎo)航觸發(fā)時(shí),全局前置守衛(wèi)按照創(chuàng)建順序調(diào)用。守衛(wèi)是異步解析執(zhí)行,此時(shí)導(dǎo)航在所有守衛(wèi)resolve完之前一直處于等待中
// 全局前置守衛(wèi)
// 特點(diǎn):可以攔截頁面跳轉(zhuǎn)
// 執(zhí)行時(shí)間:在頁面跳轉(zhuǎn)完成之前
// 參數(shù):to 表示即將前往頁面對(duì)應(yīng)的路由對(duì)象,系統(tǒng)自動(dòng)注入
// from 表示即將離開頁面的路由對(duì)象,系統(tǒng)自動(dòng)注入
// next 路由跳轉(zhuǎn)方法
router.beforeEach((to, from, next)=>{
// 用戶驗(yàn)證登錄身份
if (to.name != 'Login' && !isAuthenticated) next({ name: 'Login' })
else next();
})
??(2):全局解析守衛(wèi)router.beforeResolve
????全局解析守衛(wèi)類似于全局前置守衛(wèi),每次導(dǎo)航時(shí)都會(huì)觸發(fā),但是確保在導(dǎo)航被確認(rèn)之前,同時(shí)在所有組件內(nèi)守衛(wèi)和異步路由組件被解析之后,解析守衛(wèi)就被調(diào)用
// 全局解析守衛(wèi)
// 特點(diǎn):可以攔截頁面跳轉(zhuǎn)
// 執(zhí)行時(shí)間:在頁面跳轉(zhuǎn)完成之前
// 參數(shù):to 表示即將前往頁面對(duì)應(yīng)的路由對(duì)象,系統(tǒng)自動(dòng)注入
// from 表示即將離開頁面的路由對(duì)象,系統(tǒng)自動(dòng)注入
// next 路由跳轉(zhuǎn)方法
router.beforeResolve( async (to, from, next)=>{
// 案例
if(to.meta.verification){
try {
// 驗(yàn)證正確
await askForPage()
} catch(error) {
// 驗(yàn)證錯(cuò)誤,取消導(dǎo)航
return false
}
}
})
??(3):全局后置鉤子router.afterEach
????與守衛(wèi)不同,后置守衛(wèi)鉤子不會(huì)接受next函數(shù),也不會(huì)改變導(dǎo)航本身
// 全局后置鉤子
// 參數(shù):to 表示即將前往頁面對(duì)應(yīng)的路由對(duì)象,系統(tǒng)自動(dòng)注入
// from 表示即將離開頁面的路由對(duì)象,系統(tǒng)自動(dòng)注入
router.afterEach(to => {
// 采用路由元信息動(dòng)態(tài)更改頁面標(biāo)題
document.title = to.meta.title
})
3.路由守衛(wèi)
??(1):路由獨(dú)享守衛(wèi)beforeEnter
????路由獨(dú)享守衛(wèi)只在進(jìn)入路由時(shí)觸發(fā),參數(shù)改變時(shí)不會(huì)觸發(fā),它們只有在從一個(gè)不同的路由導(dǎo)航時(shí),才會(huì)被觸發(fā)
// 可以在路由配置上直接定義路由獨(dú)享守衛(wèi)
const router = new VueRouter({
routes: [
{
path: '/foo',
component: Foo,
beforeEnter: (to, from, next) => {
// ...
}
}
]
})
4.組件內(nèi)守衛(wèi)
const UserDetails = {
template: `...`,
beforeRouteEnter(to, from) {
// 在渲染該組件的對(duì)應(yīng)路由被驗(yàn)證前調(diào)用
// 不能獲取組件實(shí)例 `this` !
// 因?yàn)楫?dāng)守衛(wèi)執(zhí)行時(shí),組件實(shí)例還沒被創(chuàng)建!
},
beforeRouteUpdate(to, from) {
// 在當(dāng)前路由改變,但是該組件被復(fù)用時(shí)調(diào)用
// 舉例來說,對(duì)于一個(gè)帶有動(dòng)態(tài)參數(shù)的路徑 `/users/:id`,在 `/users/1` 和 `/users/2` 之間跳轉(zhuǎn)的時(shí)候,
// 由于會(huì)渲染同樣的 `UserDetails` 組件,因此組件實(shí)例會(huì)被復(fù)用。而這個(gè)鉤子就會(huì)在這個(gè)情況下被調(diào)用。
// 因?yàn)樵谶@種情況發(fā)生的時(shí)候,組件已經(jīng)掛載好了,導(dǎo)航守衛(wèi)可以訪問組件實(shí)例 `this`
},
beforeRouteLeave(to, from) {
// 在導(dǎo)航離開渲染該組件的對(duì)應(yīng)路由時(shí)調(diào)用
// 與 `beforeRouteUpdate` 一樣,它可以訪問組件實(shí)例 `this`
},
}
5.完整的導(dǎo)航解析流程
1.導(dǎo)航被觸發(fā)
2.在失活的組件里調(diào)用 beforeRouteLeave 守衛(wèi)
3.調(diào)用全局的 beforeEach 守衛(wèi)
4.在重用的組件里調(diào)用 beforeRouteUpdate 守衛(wèi)(2.2+)
5.在路由配置里調(diào)用 beforeEnter
6.解析異步路由組件
7.在被激活的組件里調(diào)用 beforeRouteEnter
8.調(diào)用全局的 beforeResolve 守衛(wèi)(2.5+)
9.導(dǎo)航被確認(rèn)
10.調(diào)用全局的 afterEach 鉤子
11.觸發(fā) DOM 更新
12.調(diào)用 beforeRouteEnter 守衛(wèi)中傳給 next 的回調(diào)函數(shù),創(chuàng)建好的組件實(shí)例會(huì)作為回調(diào)函數(shù)的參數(shù)傳入