问题描述
控制台提示如下错误:
Uncaught (in promise) Error: Redirected when going from "/login" to "/home" via a navigation guard.
原因分析
vue-router
路由版本更新产生的问题,导致路由跳转失败抛出该错误;
真正的原因是由于返回了一个 Promise
对象,正常的跳转由 then方法
执行,当正常的路由跳转被"路由导航守卫"
拦截并重新指定路由时,由于 this.$router.push()
返回的是Promise对象,此时then方法不能正常执行,无法跳转到指定路由,就触发了该对象的捕获错误的方法,throw
抛出错误,但并不影响程序功能。
解决方法
- 在被路由导航守卫拦截后,执行代码
console.clear()
, 清空控制台的报错信息; - 注意: next()方法是异步函数,需要在定时器中添加
console.clear()
,把这个操作添加进异步队列
router.beforeEach((to, from, next)=>{
if(to.meta.isShow && !getToken()){
next('/login')
setTimeout('console.clear()', 300)
return
}
next()
})
// 使用编程式导航跳转时,每次使用,后面都跟上.catch方法,捕获错误信息
this.$router.push('/location').catch(err => ())
- 通过重写VueRouter原型对象上的push方法,覆盖原来抛出异常的方法,“吞掉”异常
- 切记:一定要在router创建实例之前
import VueRouter from 'vue-router'
/* 在创建router实例对象之前,手动覆盖原型链的push来吞掉报错catch */
// 先存储默认底层的push
const originPush = VueRouter.prototype.push
// 覆盖原型链的push
VueRouter.prototype.push = function(location,resolve,reject){
// this:路由实例对象
// 判断用户有没有传后面两个可选参数
if( resolve || reject ) {
return originPush.call(this,location,resolve,reject)
} else { // 用户只传了第一个参数
/*
默认底层: catch()方法代码 throw err : 抛出异常
吞掉报错原理: 重写catch()方法,把默认底层的 throw err给去掉,就不会抛出异常
*/
return originPush.call(this,location).catch(err => {
// throw err
})
}
}
const router = new VueRouter({
routes
})
上述代码简化:
import VueRouter from 'vue-router'
const originalPush = VueRouter.prototype.push
VueRouter.prototype.push = function push(location, resolve, reject) {
if ( resolve || reject ) return originalPush.call(this, location, resolve, reject)
return originalPush.call(this, location).catch((e) => {})
}