首页 > 解决方案 > 在单个 Vue 导航中重定向两次

问题描述

在我的 Vue 应用程序中,用户的主页取决于他们的角色。为了确保向用户显示正确的主页,我使用了这个导航守卫:

export default (to, from, next) => {
  const authService = getAuthService()

  if (to.path === '/') {
    // if they've requested the home page, send them to 
    // different pages depending on their role
    if (authService.isUser()) {
      next({ name: 'events' })

    } else if (authService.isAdmin()) {
      next({ name: 'admin-events' })

    } else {
      next()
    }
  }
}

然后当用户成功登录时,我将他们重定向到'/'

  this.$router.push({path: '/'))

并且上面的导航守卫将他们重定向到他们特定角色的主页。但是,不允许在单个导航操作过程中进行两次重定向,并在第二次重定向发生时(在导航守卫中)导致控制台中出现以下错误

未捕获(承诺)错误:通过导航守卫从"/login"到时重定向。"/"

我的应用程序中发生这种情况的另一种情况是 404 组件处理尝试访问不存在的路由,即

  1. 用户尝试访问无效路由
  2. 404 组件重定向回'/'
  3. 导航守卫重定向到用户特定的主页,导致错误

有没有一种方法可以支持这些用例而无需重定向两次?

标签: vue.jsvue-router

解决方案


tldr:vm.$router.push(route)是一个承诺,需要.catch(e=>gotCaught(e))错误。


这将在下一个主要的@4中更改


目前@3 错误不区分是NavigationFailures还是regular Errors

之后的天真预期路线vm.$router.push(to)应该是to。因此,一旦发生重定向,人们就可以期待一些失败消息。将 router.push 修补为 Promise之前,该错误被静默忽略。当前的解决方案是.catch(...)在每次推送时都对 a 进行反模式,或者预测设计中的更改并将其包装以暴露失败的结果。

未来的计划是将这些信息放入结果中:

  let failure = await this.$router.push(to);
  if(failure.type == NavigationFailureType[type]){}
  else{}

Imo 这个错误只是设计使然,应该处理:

hook(route, current, (to: any) => { ... abort(createNavigationRedirectedError(current, route)) ...}

所以基本上如果to包含重定向它是一个错误,这有点等于使用vm.$router.push到警卫。

要忽略未处理的错误行为,可以传递一个空的 onComplete (在将来的版本中中断):

vm.$router.push(Route, ()=>{})

或将其包裹在try .. catch

try {

  await this.$router.push("/")
} catch {

}

这可以防止未捕获的承诺


在不重定向两次的情况下支持这一点意味着您将警卫放在出口处:

let path = "/"
navguard({path}, undefined, (to)=>this.$router.push(to||path))

这将污染重定向到主页的每个组件


顺便说一句,router-link组件使用空的 onComplete


不允许重定向两次的假设是错误的。


推荐阅读