vue路由守卫死循环及next原理解释
在使用vue路由守卫的beforeEach方法时可能会出现无限递归,也就是死循环的问题,根本原因在于next()方法在不合适的地方错误调用所致,先来看一下官方对next()方法的解释:beforeEach方法体:router.beforeEach((to, from, next) => {// ...})经过我的测试了一些数据,大概猜测出next()方法的底层实现逻辑(别问为什么不看源码,
·
在使用vue路由守卫的beforeEach
方法时可能会出现无限递归,也就是死循环的问题,根本原因在于next()方法在不合适的地方错误调用所致,先来看一下官方对next()方法的解释:
beforeEach
方法体:
router.beforeEach((to, from, next) => {
// ...
})
经过我的测试了一些数据,大概猜测出next()方法的底层实现逻辑(别问为什么不看源码,不会ts,我搞后端的)
经过我的测试,实际上,next()方法的调用是个递归的过程
以下用粗略的js代码来还原next()过程可能发生了什么,有问题请指出:
let router={}
let router.to='xxx'
let router.from='xxx'
//声明next函数
next:function(to,from,_next){
if(to===undefined){
//TODO
//相当于beforeEach里面调用next(),也就是放行,return回去,继续执行beforeEach后面的语句
return;
}else if(typeof to=='string'){
//TODO
//相当于beforeEach里面调用next('/string'),此时当前要前往的path被改变了,所以继续调用一层router.beforeEach。对新的path调用路由守卫进行校验,这种情况最容易出现死循环(死递归)
router.to=to;
router.beforeEach(router.to,rourer.from,next);
//回到上一层beforeEach,继续执行后面的代码
return;
}
}
router.beforeEach((to,from,next)=>{
//程序员TODO
})
router.beforeEach(router.to,rourer.from,next);//路由守卫调用
beforeEach和next是个轮流相互调用的过程,容易造成死循环
这里给出一种无死循环的样例:
router.beforeEach((to,from,next)=>{
console.log(to.path);
if(to.path==='/login'){
console.log(1)
next();
}else{
let user=localStorage.getItem('userInfo')?JSON.parse(localStorage.getItem('userInfo')):null;
if(user){
console.log(2)
next();
}else {
console.log(3)
next('/login');
}
}
console.log(4)
})
以下是一些测试样例:
当我未登录,前往'/content'
页面时,控制台打印情况:
/content
3
/login
1
4
4
打印内容 | 解释 |
---|---|
/content | 前往/content页面,console.log(to.path)执行 |
3 | 不是/login页面,又未在localStorage中获取到user相关信息,执行console.log(3),调用next(‘/login’)方法 |
/login | next(‘/login’)执行期间,当前要前往的url已经变成了/login,所以再一次调用beforeEach方法,方法第一行console.log(to.path);打印了当前要前往的url是/login |
1 | beforeEach方法中第二行if(to.path===‘/login’)成立,console.log(1)打印1,执行next()方法 |
4 | 因为next方法中没携带参数,又return回来了,跳过else语句,执行beforeEach方法中的console.log(4) |
4 | 回到最外层的beforeEach方法,跳过else语句,再跳出到else语句外层,执行console.log(4) |
当我未登录,前往'/login'
页面时,控制台打印情况:
/login
1
4
打印内容 | 解释 |
---|---|
/login | 当前要前往的是/login页面,beforeEach第一行console.log(to.path);打印 |
1 | if(to.path===‘/login’)成立,打印console.log(1) |
4 | 继续执行next()方法,未携带参数,next方法return回到beforeEach,跳过else语句,执行console.log(4) |
综上,尽量别在beforeEach函数内前面调用带参数的next()函数,但也不能一个next()方法都不写.
更多推荐
已为社区贡献3条内容
所有评论(0)