Vue 3 路由守卫中next()方法的深度解析与实战

5 次阅读

Vue 3 项目开发中,路由权限控制、页面跳转拦截、登录状态校验等功能几乎都会涉及路由守卫。而在 Vue Router 4 中,next() 方法曾经是路由守卫中的核心 API,许多 Vue 2 开发者也习惯使用它完成导航控制。

随着 Vue 3 和 Vue Router 4 的普及,路由守卫的写法发生了一些变化。虽然 next() 依然可以使用,但官方更推荐通过返回值控制导航流程。理解 next() 的执行机制、常见错误以及实际应用场景,对于避免路由跳转异常非常重要。

本文将围绕 Vue 3 路由守卫中的 next() 方法展开详细分析,包括基本用法、执行流程、权限验证实战、常见陷阱以及现代 Vue Router 推荐方案。

Vue 3 路由守卫基础概念

Vue Router 提供了多种导航守卫,用于在路由跳转过程中执行特定逻辑。

常见的路由守卫包括:

  • 全局前置守卫 router.beforeEach()

  • 全局解析守卫 router.beforeResolve()

  • 全局后置守卫 router.afterEach()

  • 路由独享守卫 beforeEnter

  • 组件内守卫

其中使用最多的是全局前置守卫:

JavaScript
router.beforeEach((to, from, next) => {
  // 路由跳转前执行
})

三个参数分别表示:

  • to:即将进入的目标路由对象

  • from:当前离开的路由对象

  • next:控制路由跳转的方法

next() 的作用就是告诉 Vue Router 当前导航应该如何处理。


Vue 3 路由守卫中 next() 的基本用法

1. 直接放行路由

最简单的方式:

JavaScript
router.beforeEach((to, from, next) => {
  next()
})

执行 next() 后,表示允许当前路由继续跳转。

例如:

用户访问:

/home

守卫执行:

beforeEach
↓
next()
↓
进入 home 页面

2. 跳转到指定页面

next() 可以传入路径:

JavaScript
router.beforeEach((to, from, next) => {
  next('/login')
})

表示取消当前跳转,并重新导航到 /login。

常用于:

  • 未登录用户访问受保护页面

  • 权限不足跳转提示页面

  • Token 失效重新登录

例如:

JavaScript
router.beforeEach((to, from, next) => {
  const token = localStorage.getItem('token')

  if (!token) {
    next('/login')
  }
})

不过这个代码存在一个严重问题,后续会详细说明。


3. 传递路由对象

除了字符串,也可以传递对象:

JavaScript
router.beforeEach((to, from, next) => {
  next({
    path: '/login',
    query: {
      redirect: to.fullPath
    }
  })
})

这样用户登录成功后,可以返回之前访问的页面。

例如:

用户访问:

/user/profile

发现没有登录:

跳转 /login?redirect=/user/profile

登录完成:

返回 /user/profile

这是后台管理系统中非常常见的设计。


next() 的执行机制解析

很多 Vue 3 初学者容易误解 next()。

实际上:

JavaScript
next()

并不是立即跳转,而是向 Vue Router 返回一个导航决策。

路由流程大致如下:

用户点击链接
        |
        ↓
触发导航
        |
        ↓
beforeEach守卫
        |
        ↓
执行next()
        |
        ↓
Vue Router判断结果
        |
        ↓
确认或取消导航
        |
        ↓
加载目标组件

如果守卫中没有执行 next(),导航会一直处于等待状态。

例如:

JavaScript
router.beforeEach((to, from, next) => {
  console.log('check')
})

页面会出现:

  • URL 变化异常

  • 页面无法跳转

  • 控制台没有明显错误

原因就是导航没有被放行。


next() 使用中的常见错误

错误一:忘记调用 next()

这是最常见的问题。

错误代码:

JavaScript
router.beforeEach((to, from, next) => {

  if (to.path === '/login') {
    console.log('登录页')
  }

})

无论访问什么页面,都会卡住。

正确方式:

JavaScript
router.beforeEach((to, from, next) => {

  if (to.path === '/login') {
    next()
  } else {
    next()
  }

})

错误二:重复调用 next()

例如:

JavaScript
router.beforeEach((to, from, next) => {

  if (hasToken()) {
    next()
  }

  next('/login')

})

这里执行了两次:

第一次:

允许进入页面

第二次:

跳转登录页

Vue Router 会产生:

Navigation aborted

或者:

next() called multiple times

错误。

正确写法:

JavaScript
router.beforeEach((to, from, next) => {

  if (hasToken()) {
    next()
  } else {
    next('/login')
  }

})

保证每次导航只调用一次 next()。


错误三:无限循环跳转

权限控制中非常容易出现:

JavaScript
router.beforeEach((to, from, next) => {

  if (!token) {
    next('/login')
  }

})

假设当前访问:

/login

由于没有 token:

/login
↓
next('/login')
↓
再次进入守卫
↓
next('/login')

形成死循环。

正确方式:

JavaScript
router.beforeEach((to, from, next) => {

  const token = localStorage.getItem('token')

  if (!token && to.path !== '/login') {
    next('/login')
  } else {
    next()
  }

})

核心逻辑:

只有非登录页面才需要拦截。


Vue 3 中基于 next() 实现登录权限控制

后台管理系统通常需要:

  • 登录验证

  • 页面权限判断

  • 动态菜单

  • Token 检查

例如:

路由配置:

JavaScript
const routes = [
  {
    path: '/admin',
    component: Admin,
    meta: {
      requiresAuth: true
    }
  },
  {
    path: '/login',
    component: Login
  }
]

添加守卫:

JavaScript
router.beforeEach((to, from, next) => {

  const token = localStorage.getItem('token')

  if (to.meta.requiresAuth) {

    if (token) {
      next()
    } else {
      next({
        path: '/login',
        query: {
          redirect: to.fullPath
        }
      })
    }

  } else {

    next()

  }

})

执行逻辑:

访问后台页面:

/admin

检查:

requiresAuth=true

判断:

是否存在token

存在:

进入页面

不存在:

跳转登录

Vue 3 推荐方式:使用 return 替代 next()

虽然 next() 仍然支持,但 Vue Router 4 推荐使用新的导航守卫写法。

例如:

传统方式:

JavaScript
router.beforeEach((to, from, next) => {

  if (isLogin()) {
    next()
  } else {
    next('/login')
  }

})

推荐方式:

JavaScript
router.beforeEach((to, from) => {

  if (isLogin()) {
    return true
  }

  return '/login'

})

区别:

next方式return方式
需要手动调用自动处理
容易重复调用更安全
代码复杂更简洁
Vue2习惯Vue3推荐

对于新项目,建议优先使用 return。


异步场景中的 next() 使用

实际项目中,经常需要异步检查用户信息。

例如:

JavaScript
router.beforeEach(async (to, from, next) => {

  const user = await getUserInfo()

  if (user) {
    next()
  } else {
    next('/login')
  }

})

异步守卫需要注意:

不要让多个异步流程同时执行导航。

错误:

JavaScript
router.beforeEach(async (to, from, next)=>{

  getUserInfo()

  next()

})

如果用户信息还没有加载完成,就已经进入页面,可能导致:

  • 权限判断失败

  • 菜单未加载

  • 页面数据异常

应该等待:

JavaScript
router.beforeEach(async (to, from)=>{

  const user = await getUserInfo()

  if(user){
    return true
  }

  return '/login'

})

next() 与路由权限系统结合实践

大型 Vue 3 项目通常采用:

用户登录
   |
   ↓
获取Token
   |
   ↓
请求用户信息
   |
   ↓
获取权限列表
   |
   ↓
动态生成路由
   |
   ↓
进入页面

例如:

JavaScript
router.beforeEach(async (to, from, next)=>{

  const token = store.state.token

  if(token){

    if(!store.state.userInfo){

      await store.dispatch('getUserInfo')

      await store.dispatch('generateRoutes')

      next({
        ...to,
        replace:true
      })

    }else{

      next()

    }

  }else{

    if(to.path==='/login'){
      next()
    }else{
      next('/login')
    }

  }

})

这里:

JavaScript
next({
  ...to,
  replace:true
})

用于重新触发目标路由,让动态添加的权限路由生效。


Vue 3 路由守卫开发注意事项

1. 不要滥用全局守卫

如果所有逻辑都写在:

JavaScript
beforeEach

后期维护会越来越困难。

建议拆分:

  • 登录验证模块

  • 权限模块

  • 页面标题模块

  • 数据初始化模块


2. 避免复杂业务阻塞导航

路由守卫应该快速完成判断。

不建议:

  • 大量接口请求

  • 文件上传

  • 数据计算

否则页面打开速度会明显下降。


3. 明确导航状态

复杂项目中最好记录:

  • 是否初始化完成

  • 是否获取用户信息

  • 是否加载权限路由

避免重复执行。


总结

Vue 3 路由守卫中的 next() 方法是控制导航流程的重要工具,理解它的执行规则对于开发稳定的前端应用非常关键。

使用 next() 时需要特别注意:

  • 每次导航只能调用一次

  • 所有分支必须明确结束

  • 防止登录页面无限重定向

  • 异步逻辑必须等待完成

  • 权限控制需要结合路由 meta 信息

不过在 Vue Router 4 中,官方更推荐使用 return true、return false 或 return 路由地址 的方式控制导航。对于新开发的 Vue 3 项目,优先采用返回值模式可以减少错误,让代码更加清晰。

掌握 next() 的原理和使用技巧,不仅能够解决 Vue 3 路由跳转异常问题,也能为构建大型权限管理系统打下良好的基础。