能否注册多个相同Vue路由导航守卫并按创建顺序依次执行?
多个全局导航守卫未按顺序执行的原因及解决方案
问题原因
你遇到的问题核心是对导航守卫next()方法的调用规则理解不到位。官方文档明确说明:
全局前置守卫会在每次导航触发时按照创建顺序依次调用。
这个规则本身是成立的,无法触发后续守卫的原因是:当前守卫如果调用了带跳转参数的next(路由对象),会直接终止当前完整的守卫执行队列,同时发起一次全新的导航,新的导航会重新从第一个注册的守卫开始执行,因此原队列中后续的守卫不会被触发。只有当前守卫调用了**无参数的next()**时,才会进入队列中的下一个守卫继续执行。
对应你给出的代码示例拆解执行逻辑:
假设当前用户未登录,主动访问首页路由:
- 第一轮导航触发,执行第一个守卫:判断到访问非登录页且无token,调用
next({ name: 'Logon' }),直接终止当前守卫队列,发起跳转到登录页的新导航 - 第二轮导航(跳登录页)触发,重新执行第一个守卫:判断到当前访问的是登录页,调用无参数
next(),进入第二个守卫 - 第二个守卫判断到当前访问的是登录页,调用无参数
next(),最终完成导航
如果用户已登录访问非登录页,第一个守卫会直接放行到第二个守卫,执行第二个守卫的跳转逻辑,不会出现跳过的情况,只有当前守卫触发带参数的next()跳转时才会中断队列。
解决方法
有两种常用的方案可以解决这个问题:
方案1:拆分守卫,明确执行边界
如果需要拆分为多个独立守卫,只需要保证仅最后一个守卫可以执行带参数的next()跳转,前面的守卫仅做逻辑校验,满足条件就调用无参数next()放行到下一个守卫即可。
调整后的代码示例:
// 第一个守卫:仅处理未登录拦截逻辑 router.beforeEach((to, from, next) => { if (to.name !== 'Logon' && !localStorage.getItem('authToken')) { return next({ name: 'Logon' }) } // 校验通过,放行到下一个守卫 next() }) // 第二个守卫:仅处理已登录后的校验跳转逻辑 router.beforeEach((to, from, next) => { if (to.name !== 'Logon' && localStorage.getItem('authToken')) { // 此处添加服务端校验token的逻辑 return next({ name: 'Homepage' }) } next() })
方案2:合并为单个守卫,逻辑更清晰
如果多个守卫的逻辑关联性较强,更推荐合并为单个守卫,避免队列中断的问题,也更容易维护:
router.beforeEach((to, from, next) => { const hasAuthToken = !!localStorage.getItem('authToken') // 未登录访问非登录页,跳转登录 if (to.name !== 'Logon' && !hasAuthToken) { return next({ name: 'Logon' }) } // 已登录访问非登录页,跳转首页(后续可加服务端校验逻辑) if (to.name !== 'Logon' && hasAuthToken) { return next({ name: 'Homepage' }) } // 其余情况直接放行 next() })
内容的提问来源于stack exchange,提问作者scripter2021
相关产品推荐
相关产品推荐

