前端路由守卫:掌控页面跳转的 “守门人”

在前端单页应用(SPA)中,路由系统是实现页面切换的核心。而导航守卫,就是路由系统的 "守门人",它能在路由跳转的各个阶段介入,实现权限控制、页面拦截、数据预加载等关键功能。本文将以 Vue Router 为例,全面拆解导航守卫的原理、分类和实战场景。

一、导航守卫的核心作用

单页应用的路由跳转是客户端行为,不会触发浏览器的页面刷新。导航守卫的本质,是在路由跳转的生命周期中植入钩子函数,让开发者可以:

  • 权限校验:比如未登录用户拦截到登录页、普通用户禁止访问管理员路由。
  • 数据预加载:进入页面之前请求数据,避免页面渲染后出现空白。
  • 页面拦截:比如表单未提交时,阻止用户跳转并提示保存。
  • 路由跳转日志:记录用户的页面访问轨迹,用于埋点分析。

二、导航守卫的分类与使用

Vue Router 中的导航守卫分为 3 大类,覆盖了路由跳转的完整流程:

  • 全局守卫
  • 路由独享守卫
  • 组件内守卫

2.1 全局守卫

全局守卫会作用于所有路由 ,通常在路由实例初始化时定义,分为 beforeEachbeforeResolveafterEach 三个钩子。

(1)router.beforeEach:全局前置守卫

这是最常用的全局守卫,在路由跳转前 触发,适合做全局权限控制

语法

javascript

运行

复制代码
const router = new VueRouter({ ... })

router.beforeEach((to, from, next) => {
  // to: 即将要进入的目标路由对象
  // from: 当前正要离开的路由对象
  // next: 必须调用该方法,才能进入下一个钩子
  next() // 放行
  // next(false) // 中断导航
  // next('/login') // 跳转到指定路由
  // next({ path: '/login', replace: true }) // 跳转且不留下历史记录
})

实战场景:登录校验

javascript

运行

复制代码
router.beforeEach((to, from, next) => {
  // 判断目标路由是否需要登录权限
  if (to.meta.requiresAuth) {
    const token = localStorage.getItem('token')
    if (token) {
      next() // 已登录,放行
    } else {
      next('/login') // 未登录,跳转到登录页
    }
  } else {
    next() // 不需要权限,直接放行
  }
})

// 路由配置中添加 meta 字段标记权限
const routes = [
  {
    path: '/dashboard',
    component: Dashboard,
    meta: { requiresAuth: true } // 需要登录
  },
  { path: '/login', component: Login }
]
(2)router.beforeResolve:全局解析守卫

所有组件内守卫和异步路由组件解析之后 触发,与 beforeEach 类似,但它会等待所有异步操作完成后再执行。

(3)router.afterEach:全局后置钩子

路由跳转完成后 触发,它没有 next 函数,因为此时导航已经完成,只能用于页面埋点、滚动条重置等操作。

javascript

运行

复制代码
router.afterEach((to, from) => {
  // 记录页面访问日志
  console.log(`用户从 ${from.path} 跳转到 ${to.path}`)
  // 重置页面滚动条到顶部
  window.scrollTo(0, 0)
})

2.2 路由独享守卫

路由独享守卫只作用于单个路由 ,在路由配置中通过 beforeEnter 定义,适合对特定路由进行拦截。

语法与实战

javascript

运行

复制代码
const routes = [
  {
    path: '/admin',
    component: Admin,
    meta: { requiresAuth: true },
    beforeEnter: (to, from, next) => {
      // 仅对 /admin 路由生效的权限校验
      const isAdmin = localStorage.getItem('role') === 'admin'
      if (isAdmin) {
        next()
      } else {
        next('/403') // 无权限跳转到 403 页面
      }
    }
  }
]

2.3 组件内守卫

组件内守卫是定义在组件内部 的钩子,用于监听组件自身的路由跳转,分为 beforeRouteEnterbeforeRouteUpdatebeforeRouteLeave

(1)beforeRouteEnter:进入组件前触发

注意 :此时组件实例还未创建(thisundefined),若要访问组件实例,需通过 next 的回调函数。

javascript

运行

复制代码
export default {
  beforeRouteEnter (to, from, next) {
    // 通过 next 回调访问组件实例
    next(vm => {
      // vm 就是组件实例
      vm.fetchData() // 进入组件前预加载数据
    })
  }
}
(2)beforeRouteUpdate:路由参数更新时触发

当路由参数变化但组件被复用(比如 /user/:id/user/1 跳转到 /user/2)时触发,可用于更新组件数据。

javascript

运行

复制代码
export default {
  beforeRouteUpdate (to, from, next) {
    // 更新路由参数对应的用户信息
    this.userId = to.params.id
    this.fetchUserInfo()
    next()
  }
}
(3)beforeRouteLeave:离开组件时触发

适合做页面离开拦截,比如表单未提交时提示用户。

javascript

运行

复制代码
export default {
  data () {
    return {
      formData: {},
      isDirty: false // 标记表单是否修改
    }
  },
  beforeRouteLeave (to, from, next) {
    if (this.isDirty) {
      const confirm = window.confirm('表单未保存,确定离开吗?')
      if (confirm) {
        next()
      } else {
        next(false) // 取消导航
      }
    } else {
      next()
    }
  }
}

三、导航守卫的执行顺序

当一个路由跳转触发时,各类守卫的执行顺序是固定的,遵循 "前置 → 解析 → 组件内 → 后置" 的流程:

  1. 全局前置守卫 beforeEach
  2. 路由独享守卫 beforeEnter
  3. 组件内守卫 beforeRouteEnter
  4. 全局解析守卫 beforeResolve
  5. 导航完成
  6. 全局后置钩子 afterEach
  7. 组件内守卫 beforeRouteEnternext 回调

四、常见问题与注意事项

4.1 不要忘记调用 next

beforeEachbeforeEnter 等带 next 的守卫中,必须调用 next() 才能继续导航,否则会导致路由跳转卡住。

4.2 避免无限循环

如果在守卫中跳转到自身路由,会触发无限循环,比如:

javascript

运行

复制代码
// 错误示例:会无限触发 beforeEach
router.beforeEach((to, from, next) => {
  if (to.path !== '/login') {
    next('/login') // 若 /login 也触发该守卫,会无限循环
  }
})

解决方法:添加条件判断,避免重复跳转。

4.3 异步操作的处理

如果在守卫中执行异步操作(比如请求接口校验权限),需要在异步回调中调用 next

javascript

运行

复制代码
router.beforeEach((to, from, next) => {
  // 异步校验权限
  checkPermission().then(res => {
    if (res) next()
    else next('/403')
  })
})

五、总结

导航守卫是前端路由系统的核心能力,它让开发者能够精准掌控路由跳转的每一个环节。无论是 Vue Router 还是 React Router(通过 useNavigateuseLocation 等钩子实现类似功能),导航守卫的设计思想都是一致的 ------在生命周期中植入钩子,实现业务逻辑的灵活介入

掌握导航守卫的分类和执行顺序,就能轻松应对权限控制、数据预加载等常见需求,让单页应用的路由跳转更安全、更智能。

👉 **觉得有用的点点关注谢谢~**

相关推荐
梦帮科技5 小时前
GRAVIS v4.0:基于Web的极速套利架构设计与实时数据流实现
前端·人工智能·rust·自动化·区块链·智能合约·数字货币
爱勇宝6 小时前
办公资料反复修改、补传、交接混乱,我做了个桌面工具来解决这件事
前端·后端·程序员
微信开发api-视频号协议7 小时前
企业微信外部群开发自动化实践过程
java·前端·微信·自动化·企业微信·ipad
甲维斯7 小时前
Fable5:20美金的顶级设计师!
前端·人工智能
kyriewen7 小时前
我同时用了 Claude Code、Cursor 和 Codex,说说三个工具的真实差距——2026 年选错工具比不用 AI 更浪费时间
前端·ai编程·claude
Jackson__7 小时前
为了拯救我的腰椎和颈椎,我做了款浏览器插件!
前端·javascript·开源
闲猫7 小时前
Python FastAPI + SQLAlchemy 入门教程:从零搭建你的第一个 Web 应用
前端·python·fastapi
林小帅8 小时前
NestJS v11 + Prisma v7 ESM 迁移配置解析
前端·javascript·后端
IT_陈寒8 小时前
React的setState竟然不是立刻生效的,害我调试半天
前端·人工智能·后端
简简单单就是我_hehe8 小时前
前端埋点日志解决方案:完整 User-Agent 解析工具实现,爬虫识别、设备品牌、操作系统、浏览器版本全解析(附完整源码)
前端·爬虫