router.beforeEach註冊了一個全局前置守衛,每當通過vue-router跳轉都會先執行這裏,相當於過濾器.
beforeEach接收3個參數
to 表示即將要進入的目標路由對象,
from 表示當前導航正要離開的路由,
next() 一定要調用該方法來 resolve 這個鉤子。執行效果依賴 next 方法的調用參數。
next(): 進行管道中的下一個鉤子。如果全部鉤子執行完了,則導航的狀態就是 confirmed (確認的)。
next(false): 中斷當前的導航。如果瀏覽器的 URL 改變了 (可能是用戶手動或者瀏覽器後退按鈕),那麼 URL 地址會重置到 from 路由對應的地址。
next(’/’) 或者 next({ path: ‘/’ }): 跳轉到一個不同的地址。當前的導航被中斷,然後進行一個新的導航。你可以向 next 傳遞任意位置對象,且允許設置諸如 replace: true、name: ‘home’ 之類的選項以及任何用在 router-link 的 to prop 或 router.push 中的選項。
確保要調用 next 方法,否則鉤子就不會被 resolved。
以下是路由配置的一部分代碼
router.beforeEach((to,from,next)=>{
NProgress.start() // 頂部bar
if(getToken()){//判斷是否有token
if(to.path==='/login'){
next({path:'/'})//跳轉到/
}else{
next();
if(store.getters.roles.length === 0){//判斷當前用戶是否已經拉取到user_info信息
store.dispatch('GetUserInfo').then(res=>{ //執行vuex中的action
const roles = res.data.roles //roles must be a array,示例['admin']
store.dispatch('GenerateRoutes',{ roles }).then(()=>{// 根據roles權限生成可訪問的路由表
router.addRoutes(store.getters.addRouters)// 動態添加可訪問路由表
next({...to,replace:true})//hack方法 確保addRoutes已完成 ,set the replace: true so the navigation will not leave a history record
})
}).catch((err)=>{
store.dispatch('LogOut').then(()=>{//LogOut
Message.error(err||'Verification failed,please login again')
next({path:'/'})//重新定義
})
})
} else{
//沒有動態改變權限的需求可直接next()刪除下方的權限判斷
if(hasPermission(store.getters.roles,to.meta.roles)){
next()
}else{
next({ path: '/401', replace: true, query: { noGoBack: true }})
}
}
}
}else{
if(whiteList.indexOf(to.path) !== -1){//在免登錄白名單,直接進入
next()
}else{
next(`/login?redirect=${to.path}`)//// 否則全部重定向到登錄頁
NProgress.done() // if current page is login will not trigger afterEach hook, so manually handle it
}
}
});
router.afterEach(() => {
NProgress.done() // finish progress bar
})