vue的路由守衛(wèi),也叫路由鉤子、導(dǎo)航守衛(wèi)或?qū)Ш姐^子。路由(vue-router) 提供的導(dǎo)航守衛(wèi)主要用來(lái):通過(guò)跳轉(zhuǎn)或取消的方式守衛(wèi)導(dǎo)航。有多種機(jī)會(huì)植入路由導(dǎo)航過(guò)程中:全局的,單個(gè)路由獨(dú)享的, 或者組件級(jí)的。
注意:參數(shù)或查詢(xún)的改變并不會(huì)觸發(fā)進(jìn)入/離開(kāi)的導(dǎo)航守衛(wèi)。
1.全局路由守衛(wèi)
-
全局前置守衛(wèi)
使用router.beforeEach注冊(cè)全局的前置路由守衛(wèi)。
// index.js
const router=new VueRouter({...})
router.beforeEach((to,from,next)=>{
//...
})
當(dāng)一個(gè)導(dǎo)航觸發(fā)時(shí),全局前置守衛(wèi)按照創(chuàng)建順序調(diào)用。守衛(wèi)是異步解析執(zhí)行,此時(shí)導(dǎo)航在所有守衛(wèi) resolve 完之前一直處于等待中。
方法接收三個(gè)參數(shù):
to: Route ,即將要進(jìn)入的目標(biāo) 路由對(duì)象
from: Route,當(dāng)前導(dǎo)航正要離開(kāi)的路由
next: Function,一定要調(diào)用該方法來(lái)resolve這個(gè)鉤子。執(zhí)行效果依賴(lài) next 方法的調(diào)用參數(shù)。
?next():進(jìn)行管道中的下一個(gè)鉤子。如果全部鉤子執(zhí)行完了,則導(dǎo)航的狀態(tài)就是confirmed (確認(rèn)的)。
?next(false): 中斷當(dāng)前的導(dǎo)航。如果瀏覽器的 URL 改變了 (可能是用戶(hù)手動(dòng)或者瀏覽器后退按鈕),那么 URL 地址會(huì)重置到 from 路由對(duì)應(yīng)的地址。
?next('/') 或者 next({ path: '/' }):跳轉(zhuǎn)到一個(gè)不同的地址。當(dāng)前的導(dǎo)航被中斷,然后進(jìn)行一個(gè)新的導(dǎo)航。你可以向 next 傳遞任意位置對(duì)象,且允許設(shè)置諸如 replace: true、name: 'home' 之類(lèi)的選項(xiàng)以及任何用在router-link的 to prop或 router.push中的選項(xiàng)。
?next(error):(2.4.0+) 如果傳入 next 的參數(shù)是一個(gè) Error 實(shí)例,則導(dǎo)航會(huì)被終止且該錯(cuò)誤會(huì)被傳遞給 router.onError()注冊(cè)過(guò)的回調(diào)。
確保要調(diào)用 next方法,否則鉤子就不會(huì)被 resolved。
-
全局后置守衛(wèi)
使用router.afterEach注冊(cè)全局的后置守衛(wèi)。
//index.js
const router=new VueRouter({...})
router.afterEach((to,from)=>{
//...
})
不同于前置守衛(wèi)的是,后置守衛(wèi)沒(méi)有next 函數(shù),也不會(huì)改變導(dǎo)航本身。
-
全局解析守衛(wèi)
這個(gè)是vue2.5.0版本新增的。使用router.beforeReslolve注冊(cè)全局的解析守衛(wèi)。
//index.js
const router=new VueRouter({...})
router.beforeReslolve((to,from,next)=>{
//...
})
這和 router.beforeEach 類(lèi)似,區(qū)別在于:在導(dǎo)航被確認(rèn)之前,同時(shí)在所有組件內(nèi)守衛(wèi)和異步路由組件被解析之后,解析守衛(wèi)就被調(diào)用。
2.路由獨(dú)享的守衛(wèi)
顧名思義,即單個(gè)路由獨(dú)享的導(dǎo)航鉤子,使用boforeEnter在路由配置上直接進(jìn)行注冊(cè)。
// router.js
const router=new VueRouter({
routes:[
{
path:'/login',
name:'login',
component:()=>import('@/components/Login/Login'),
beforeEnter: (to,from,next) => {
// ...
}
}
]
})
使用方法與全局守衛(wèi)相同,不同點(diǎn)在于:全局守衛(wèi)可以作用于全局,路由獨(dú)享守衛(wèi)只作用于被設(shè)置守衛(wèi)的路由。
3.組件級(jí)的守衛(wèi)
組件內(nèi)的守衛(wèi)分為beforeRouteEnter、beforeRouterUpdate和beforeRouteLeave。
-
beforeRouteEnter
在渲染該組件的對(duì)應(yīng)路由被 confirm 前調(diào)用。
<script>
export default{
data(){
return{
}
},
beforeRouteEnter:(to,from,next) => {
// ...
},
}
</script>
注意:beforeRouteEnter 不能獲取組件實(shí)例 this,因?yàn)楫?dāng)守衛(wèi)執(zhí)行前,組件實(shí)例被沒(méi)有被創(chuàng)建出來(lái),剩下兩個(gè)鉤子則可以正常獲取組件實(shí)例 this。
但是并不意味著在 beforeRouteEnter 中無(wú)法訪問(wèn)組件實(shí)例,我們可以通過(guò)給 next 傳入一個(gè)回調(diào)來(lái)訪問(wèn)組件實(shí)例。在導(dǎo)航被確認(rèn)時(shí),會(huì)執(zhí)行這個(gè)回調(diào),這時(shí)就可以訪問(wèn)組件實(shí)例了。
<script>
export default{
data(){
return{
name:'MM'
}
},
beforeRouteEnter:(to,from,next) => {
next(vm=>{
console.log("hello,"+vm.name) //hello,MM
})
},
}
</script>
注意:僅僅是 beforRouteEnter 支持給 next 傳遞回調(diào),其他兩個(gè)并不支持。因?yàn)闅w根結(jié)底,支持回調(diào)是為了解決 this 問(wèn)題,而其他兩個(gè)鉤子的 this 可以正確訪問(wèn)到組件實(shí)例,所有沒(méi)有必要使用回調(diào)。
-
beforeRouteUpdate
這個(gè)方法是vue-router2.2版本加上的。因?yàn)樵瓉?lái)的版本中,如果一個(gè)在兩個(gè)子路由之間跳轉(zhuǎn),是不觸發(fā)beforeRouteLeave的。這會(huì)導(dǎo)致某些重置操作,沒(méi)地方觸發(fā)。在之前,我們都是用watch 的。但是通過(guò)這個(gè)鉤子,我們有了更好的方式。
<script>
export default{
data(){
return{
}
},
beforeRouteUpdate:(to,from,next) => {
// ...
},
}
</script>
-
beforeRouteLeave
這個(gè)離開(kāi)守衛(wèi)通常用來(lái)禁止用戶(hù)在還未保存修改前突然離開(kāi)。該導(dǎo)航可以通過(guò) next(false) 來(lái)取消。
<script>
export default{
data(){
return{
}
},
beforeRouteLeave:(to,from,next) => {
// ...
},
}
</script>