vue路由跳转错误:Uncaught (in promise) Error: Redirected when going from “/layout/home” to “/layout/user” via a navigation guard.

问题重现及产生原因

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tB7n3BoM-1627995094220)(11/image-20210803203152516.png)]
原因:
  vue-router路由版本更新产生的问题,导致路由跳转失败抛出该错误;
真正的原因是由于返回了一个Promise对象, 正常的跳转由then方法执行 当正常的路由跳转, 被"路由导航守卫"拦截并重新指定路由时, 由于 this.$router.push() 返回的是Promise对象, 此时then方法不能正常执行, 无法跳转到指定路由, 就触发了该对象的捕获错误的方法, throw抛出错误, 但并不影响程序功能.




  1. 在项目开发中,并不是每一个路由跳转都是明确的。 例如很多页面跳转需要登录判断,如果你有登录,则跳转到指定页面,没有登录则跳转到登录页面。

项目代码:

  1. 项目中, 使用路由跳转页面, this.&router.push() 这个方法, 返回Promise对象, 如果不能正常跳转, 内部会抛出错误, 但是这个错误并不影响程序执行, 如果想解决控制台打印报错信息, 有3种方法

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-K88puIDk-1627995094222)(11/image-20210803203107821.png)]





解决方式一: 投机取巧式

  • 在被路由导航守卫拦截后, 执行代码 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)=>{})
}
Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐