vue2路由導航守衛(鉤子函式)
官方:vue-router 提供的導航守衛主要用來通過跳轉或取消的方式守衛導航。有多種機會植入路由導航過程中:全域性的, 單個路由獨享的, 或者元件級的。
所謂的Vue路由導航守衛,也就是我們常說的生命週期鉤子函式,鉤子函式的意思就是在特定的時刻,Vue會自動觸發這個方法,我們可以通過這些個鉤子函式,實現一些功能,比如,某些頁面需要登入後才可以訪問,某些頁面需要使用者達到什麼等級才可以訪問,又或者是跳轉頁面後修改一些資訊等等,我們就可以通過路由導航守衛來攔截並做相應的處理
全域性守衛:
掛載在router例項上
-
全域性前置鉤子
注意:引數或查詢的改變並不會觸發進入/離開的導航守衛。你可以通過觀察 $route 物件來應對這些變化,或使用 beforeRouteUpdate 的元件內守衛。
router.beforeEach((to,from,next)=>{
//to: Route: 即將要進入的目標 路由物件
//from: Route: 當前導航正要離開的路由
//next: Function:如果你想要進入下一個導航,就必須要呼叫next()方法,否則不會進入下一個導航
})
官方對於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() 註冊過的回撥。
看個小示例:
router.beforeEach((to,from,next)=>{ if(to.matched.some((item)=>item.meta.login)){ console.log(to) //router.app就是我們的根例項 let info = router.app.$local.fetch('miaov') // console.log(info) if(info.login){ next() }else{ router.push({ path:'/login' }) } }else{ next() } })
-
全域性後置鉤子:
注意:這些鉤子不會接受next函式,也不會改變導航本身
router.afterEach((to,from)=>{
})
區域性鉤子函式
區域性鉤子函式可以寫在兩個地方,一個是寫在元件對應的路由配置中,一個是直接寫在元件中
路由獨享的守衛:
可以在路由配置上直接定義beforeEnter守衛:
const router = new VueRouter({
routes: [
{
path: '/foo',
component: Foo,
beforeEnter: (to, from, next) => {
// ...
//引數和前置守衛的引數含義一樣
}
}
]
})
元件內的守衛:
- beforeRouteEnter
- beforeRouteUpdata(2.2新增)
- beforeRouteLeave
beforeRouteEnter(to,from,next){
//在渲染該元件的對應路由被confirm前呼叫
//不能獲取元件例項“this”
//因為當守衛執行前,元件例項還沒被建立
}
beforeRouteEnter 守衛不能訪問this,因為守衛在導航確認前被呼叫,因此即將登場的新組建還沒被建立
可以通過傳一個回撥給next來訪問元件例項。在導航被確認的時候執行回撥,並且把元件例項作為回撥方法的引數
export default {
data(){
return {
flag: ''
}
},
watch: {
$route(){
this.flag = flags[this.$route.path.slice(1)]
}
},
beforeRouteEnter(to, from, next){//複用的,不會重新走鉤子函式, 所以需要watch監控路由資訊物件
next((vm) => {
vm.flag = flags[to.path.slice(1)]
})
},
components: {
headerNav: Header
/*(resolve) => {
setTimeout(() => {
resolve(require('@/components/header'))
}, 2000)
}*/
}
}
注意:beforeRouteEnter是支援給next傳遞迴調的唯一守衛。對於beforeRouteUpdate和beforeRouteLeave來說
this已經可用了,所以不支援傳遞迴調
beforeRouteUpdate(to,from,next){
//在當前路由改變,但是該元件被複用時呼叫
//可以訪問元件例項this
}
這個函式應用場景比較特殊一點,當元件中有子導航時,我們就可以在這個父元件中使用這個方法來監控子路由的跳轉了,然後再父元件中做出相應的處理,除了使用beforeRouteUpdate()函式外,我們還可以在父元件中使用watch來監控路由的變化,效果是差不多的,嗯,根據實際情況來判斷該使用哪一種方式處理
看個簡單的小例子:
export default {
data(){
return{
test:0
}
},
//方法一
watch:{
$route(){
this.test++
}
},
beforeRouteEnter(to,from,next){
//this是個undefined,因為元件的例項還沒有建立
next((vm)=>{
vm.test++
});//next中可以接收一個回撥函式
},
/* 方法二
// beforeRouteUpdate(to,from,next){
// this.test++
// next();
// },
*/
beforeRouteLeave(to,from,next){
next();
},
name: "about"
}
beforeRouteLeave(to,from,next){
//導航離開該元件的對應路由時呼叫
//可以訪問元件例項this
}
離開守衛通常用來禁止使用者在還未儲存修改前突然離開。該導航可以通過next(false)來取消