在设计路由的时候,会在路由循环时,根据某些状态,来判断页面后续应该如何跳转。常见的例子,就是登陆时,判断用户是否已经登录,再决定是跳转到用户的目标页面,还是返回到登录页。
常见的设计是这样的:
router.beforeEach((to, from, next) => {
if (判断用户是否登录) {
next()
} else {
if (to.path === '/') {
next()
} else {
next("/")
}
}
})
如果用户是登录的,那么直接调用 next() ,用户可以去往想去的页面;
如果用户未登录,但是他想打开的是登录页,好,我们也放他过去;
如果用户未登录,且想打开的不是登录页,那不行,我们得拦截住他:“你没登陆,你得去登录页”。
好,现在问题来了:当我们从登录页("/")页,登录成功,想跳转到某个页面时(例如首页"/home"),由于我们写了一个BUG,导致登录失败时,我们也通过API进行了跳转操作(this.$router.push),我们看到的效果是,路由进行了拦截,页面又回到了登录页("/")。从现象上来说,是正确的,但是我们打开控制台,好,一片红:
啥意思?从字面意思上说:当从"/"通过路由守卫跳转到"/home"时,发生了重定向。
很好理解,我们从登录页("/")跳转到首页("/home")时,在路由守卫中被拦截了,又回到了登录页("/")。所以,这个错误看起来更像是一个警告,而不是一个错误。
那么问题来了,开始在某个页面,向外跳转时,经过一系列重定向,又回到了这个页,会报错嘛?为什么?
我们再做一个实验:
router.beforeEach((to, from, next) => {
next(false)
})
代码很简单,不同意任何跳转。
结果是一样的,依然报了和图中一样的错。
出错的原因,我猜测可能是router的API有问题,可能是返回值有问题,也可能异步代码有问题,暂时还没深究。先说说处理,使用 return 来阻断函数执行:
router.beforeEach((to, from, next) => {
console.log(`路由从 " ${from.path} " 变到 " ${to.path} " 。`);
// 做一些判断逻辑
// 注意死循环的问题
if (window.sessionStorage.getItem("login")) {
next()
} else {
if (to.path === '/') {
next()
} else {
// 未登录,且不是去往首页,则跳转到首页
if (from.path === '/') {
// 直接终止路由的变化
// next(false)
return;
} else {
// 重定向到首页
next("/")
}
}
}
})
这个错误仅仅出现在API调用时,而且实际中几乎是不会发生,所以我们可以使用return来处理掉可能出的错就可以了。