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

在前端单页应用(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 等钩子实现类似功能),导航守卫的设计思想都是一致的 ------在生命周期中植入钩子,实现业务逻辑的灵活介入

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

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

相关推荐
jiayong235 小时前
前端性能优化系列(二):请求优化策略
前端·性能优化
H_ZMY5 小时前
前端实现 HTTPS 强制跳转与移动端域名自动适配
前端·网络协议·https
We་ct5 小时前
LeetCode 42. 接雨水:双指针解法深度剖析与全方法汇总
前端·算法·leetcode·typescript
灰海5 小时前
vue实现即开即用的AI对话打字机效果
前端·javascript·vue.js·打字机
智绘前端5 小时前
React 组件开发速查卡
前端·react.js·前端框架
箫笙默6 小时前
前端相关技术简介
前端
Ulyanov6 小时前
Impress.js深度技术解析:架构基础与结构化设计
开发语言·前端·javascript
小宇的天下6 小时前
Calibre :Standard Verification Rule Format(SVRF) Manual (1-1)
大数据·前端·网络
充气大锤6 小时前
前端实现流式输出配合katex.js
开发语言·前端·javascript·ai·vue