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
})