#动态添加路由到的坑\
- * *
动态添加路由遇到死循环
检查一下404是不是在常量路由中
最好每次打开页面只动态加载一次,在前置守卫中添加判断\
动态添加路由函数,注意404页面要在这最后添加到路由表中,不能放在router默认的路由中,否则刷新页面就会跳转到404
具体看这www.cnblogs.com/windok/p/13…
const whiteList = ['/login'] // no redirect whitelist
router.beforeEach(async (to, from, next) => {
NProgress.start()
document.title = getPageTitle(to.meta.title)
const hasToken = getToken()
if (hasToken) {
//如果有token
if (to.path === '/login') {
//如果已登陆还要直接去登录页面,那直接让他去主页吧,此时用户只能手动退出登录
next({ path: '/' })
NProgress.done()
} else {
//如果登录状态下要去到别的路径,判断有没有用户名字。
const hasGetUserInfo = store.getters.name
if (hasGetUserInfo) {
//有用户名字直接走吧。
next()
} else {
try {
//没有的话重新获取
store.dispatch('user/getInfo')
next({ ...to, replace: true })
} catch (error) {
//如果还没有获取到,删除token,跳回登录
store.dispatch('user/resetToken')
Message.error(error || 'Has Error')
next('/login')
NProgress.done()
}
}
}
} else {
/* 根本就没有token*/
if (whiteList.indexOf(to.path) !== -1) {
// 这里是白名单,有没有token都可以进入,现在只有登录页面在白名单
next()
} else {
// 其他没有访问权限的页面重定向到登录页面。
next(/login?redirect=${to.path})
NProgress.done()
}
}
})
router.afterEach(() => {
// finish progress bar
NProgress.done()
})
引用一篇文章中的思路
可以这么理解:next() 是放行,但是如果next()里有参数的话,next()就像被重载一样,就有了不同的功能。而对于上面说的中断当前导航,执行新的导航打个比方:现在我有一个守卫,在守卫中我使用next('/login'),肯定有同学认为是会直接跳转到/login路由:
beforeEach((to, from, next) =>{\ next('/login')\ }
然而执行时需要这么看:
beforeEach((to, from, next) => { \ beforeEach(('/login', from, next) => {\ beforeEach(('/login', from, next) => {\ beforeEach(('/login', from, next) => {\ beforeEac... // 一直循环下去...... , 因为我们没有使用 next() 放行\ }\ }\ }\ }
如果把这个守卫改一下,当我在地址栏输入/home时
beforeEach((to, from, next) => {\ if(to.path === '/home') {\ next('/login')\ } else {\ // 如果要去的地方不是 /home , 就放行\ next()\ }\ }
我本来要去/home路由,因此执行了第一次 beforeEach((to, from, next)但是这个路由守卫中判断了如果要去的地方是'/home',就执行next('/login'),所以想要访问/home可以这么看
beforeEach((to, from, next) => {\ beforeEach(('/login', from, next) => {\ next() // 现在要去的地方不是 /home , 因此放行\ }\ }
注意:重点就在这,next('/login')不是说直接去/login路由,而是中断(不是CPU的那个中断!VUE中的中断就是此时不会执行router.afterEach(() => {})这一次路由守卫的操作,又进入一次路由守卫,就像嵌套一样,一层路由守卫,然后又是一层路由守卫,此时路由守卫进入到第二层时,to.path已经不是/home了,这个时候才执行next()放行操作。
正以为如此很多人在使用动态添加路由addRoutes()会遇到下面的情况:在addRoutes()之后第一次访问被添加的路由会白屏,这是因为刚刚addRoutes()就立刻访问被添加的路由,然而此时addRoutes()没有执行结束,因而找不到刚刚被添加的路由导致白屏。因此需要从新访问一次路由才行。该如何解决这个问题 ?
此时就要使用next({ ...to, replace: true })来确保addRoutes()时动态添加的路由已经被完全加载上去。
next({ ...to, replace: true })中的replace: true只是一个设置信息,告诉VUE本次操作后,不能通过浏览器后退按钮,返回前一个路由。
因此next({ ...to, replace: true })可以写成next({ ...to }),不过你应该不希望用户在addRoutes()还没有完成的时候,可以点击浏览器回退按钮搞事情吧。
其实next({ ...to })的执行很简单,它会判断:
如果参数to不能找到对应的路由的话,就再执行一次beforeEach((to, from, next)直到其中的next({ ...to})能找到对应的路由为止。
也就是说此时addRoutes()已经完成啦,找到对应的路由之后,接下来将执行前往对应路由的beforeEach((to, from, next) ,因此需要用代码来判断这一次是否就是前往对应路由的beforeEach((to, from, next),如果是,就执行next()放行。
如果守卫中没有正确的放行出口的话,会一直next({ ...to})进入死循环 !!!
因此你还需要确保在当addRoutes()已经完成时,所执行到的这一次beforeEach((to, from, next)中有一个正确的next()方向出口。
www.cnblogs.com/windok/p/14…\