Vue3 路由守卫详解:全局守卫、路由独享守卫、组件内守卫

一、前言

Vue3开发中,路由守卫是一个非常重要的知识点。很多常见需求都离不开它,比如:

  • 页面权限控制

  • 登录校验

  • 动态路由参数校验

  • 页面离开提醒

  • 路由切换时执行额外逻辑

路由守卫本质上就是:在路由跳转的不同阶段,执行指定逻辑,对跳转过程进行控制。

本文重点整理三类最常用的守卫:

  • 全局路由守卫

  • 路由独享守卫

  • 组件内守卫

尽量聚焦在"是什么、怎么用、有什么作用"


二、什么是路由守卫

路由守卫可以理解为一种"拦截机制"。

当用户准备从一个页面跳转到另一个页面时,Vue Router 会在跳转前、跳转后,或者组件更新过程中,给我们一些可以插入逻辑的时机。我们可以在这些时机中:

  • 放行跳转

  • 拦截跳转

  • 重定向到其他页面

  • 执行提示、日志、校验等逻辑

简单说,路由守卫解决的是:

页面不是想进就进,也不是想走就走,而是先经过规则判断。


三、路由守卫的分类

Vue Router 中常见的路由守卫主要有三类:

1. 全局守卫

对所有路由都生效,适合处理整个项目通用的逻辑。

2. 路由独享守卫

只对某一个具体路由生效,适合处理该路由特有的逻辑。

3. 组件内守卫

写在页面组件内部,适合处理和当前组件强相关的逻辑。

可以先记住一句话:

全局守卫管整体,独享守卫管单个路由,组件内守卫管当前页面组件。


四、全局路由守卫

1. 什么是全局前置守卫

全局前置守卫会在每次路由跳转前执行,常用写法如下:

TypeScript 复制代码
router.beforeEach((to, from, next) => {
  next()
})

参数说明:

  • to:准备进入的目标路由

  • from:当前离开的路由

  • next:控制是否继续跳转

它最常见的作用就是:

  • 登录校验

  • 权限控制

  • 根据路由信息做统一判断


2. 全局前置守卫的典型用法

一个很常见的场景是:某些页面必须登录后才能访问。

示例:

TypeScript 复制代码
router.beforeEach((to, from, next) => {
  if (to.meta.login) {
    const token = localStorage.getItem('token')
    if (!token) {
      next('/login')
      return
    }
  }
  next()
})

这段代码的逻辑是:

  1. 每次跳转前先进入守卫

  2. 判断目标路由是否需要登录

  3. 如果需要登录,就去本地检查token

  4. 没有token就跳转到登录页

  5. 有token就正常放行

这里的重点不是代码本身,而是理解这种设计思路:

把通用的权限判断统一放到全局前置守卫里处理。


3.meta的作用

在做权限控制时,通常会结合路由元信息meta一起使用,例如:

TypeScript 复制代码
{
  path: '/admin',
  name: 'admin',
  component: Admin,
  meta: {
    login: true,
    title: '后台管理'
  }
}

这里的meta 可以理解为:给路由额外附加的自定义信息。

例如:

  • login:true 表示这个页面需要登录

  • title:可以用来设置页面标题

好处是:

  • 规则和路由配置写在一起,结构清晰

  • 全局守卫可以统一读取这些信息

  • 后期扩展角色权限也比较方便


4. 全局后置守卫

全局后置守卫会在路由跳转完成后执行,写法如下:

TypeScript 复制代码
router.afterEach((to, from) => {
  console.log('路由跳转完成')
})

它的常见用途有:

  • 记录日志

  • 页面埋点统计

  • 修改文档标题

注意两点:

  • afterEach没有next

  • 它不能阻止跳转

所以它更适合做"跳转完成之后的附加处理"。


五、路由独享守卫

1. 什么是路由独享守卫

路由独享守卫是只对某个路由生效的守卫,直接写在路由配置对象中,常用写法如下:

TypeScript 复制代码
{
  path: '/article/:id',
  name: 'article',
  component: Article,
  beforeEnter(to, from, next) {
    next()
  }
}

它适合处理某一个页面自己的进入规则,而不是整个项目的通用规则。


2. 路由独享守卫的典型作用

最常见的用途之一就是:进入页面前先校验路由参数。

例如文章详情页通常会写成:

TypeScript 复制代码
{
  path: '/article/:id',
  name: 'article',
  component: Article,
  beforeEnter(to, from, next) {
    const id = Number(to.params.id)
​
    if (isNaN(id)) {
      next(from)
      return
    }
​
    next()
  }
}

这里的意思是:

  • id本来应该是数字

  • 如果用户手动输入了错误地址,比如/article/xxx

  • 那么就不让它正常进入详情页

这就是路由独享守卫非常典型的使用方式:

只为某一个路由,增加进入前的专属校验。


3. 为什么这里不用全局守卫

因为这个参数校验只对文章详情页有效,不适用于其他页面。

如果强行写到全局守卫里,会带来两个问题:

  • 逻辑变杂,职责不清

  • 其他页面也会无意义地经过这段判断

所以这类"只属于某个页面"的规则,更适合写在 beforeEnter 中。


六、组件内守卫

组件内守卫写在页面组件内部,适合处理和当前页面组件密切相关的逻辑。

Vue Router里比较常见的两个组合式 API 写法是:

  • onBeforeRouteUpdate

  • onBeforeRouteLeave


1. onBeforeUpdate的作用

它会在当前路由更新,但组件被复用时触发。

示例:

TypeScript 复制代码
import { onBeforeRouteUpdate } from 'vue-router'
​
onBeforeRouteUpdate((to, from, next) => {
  console.log('路由参数变化时触发')
  next()
})

这个守卫特别适合详情页场景。

比如当前在:

TypeScript 复制代码
/article/1

然后跳转到:

TypeScript 复制代码
/article/2

这时很多情况下并不会重新创建一个新组件,而是复用原来的组件实例。也就是说,虽然地址变了,但页面组件还是同一个。

这时候如果你只在组件初次加载时处理数据,很可能拿不到更新后的参数,因此就需要 onBeforeRouteUpdate

它的作用可以概括为:

  • 监听同一组件下的路由变化

  • 在参数变化时重新处理逻辑

  • 适合重新请求详情数据


2. onBeforeRouteLeave的作用

它会在当前组件对应的路由即将离开时触发。

示例:

TypeScript 复制代码
import { onBeforeRouteLeave } from 'vue-router'
​
onBeforeRouteLeave((to, from, next) => {
  console.log('路由离开时触发')
  next()
})

它常见的作用有:

  • 离开表单页前提醒用户

  • 未保存内容时阻止离开

  • 离开页面前做一些清理工作

例如:

TypeScript 复制代码
onBeforeRouteLeave((to, from, next) => {
  const leave = window.confirm('当前内容未保存,确定离开吗?')
  if (!leave) return
  next()
})

这类需求在后台管理系统和表单页面里非常常见。


七、三类守卫的区别总结

守卫类型 写在哪里 作用范围 常见用途
全局守卫 路由实例上 所有路由 登录校验、权限控制、埋点
路由独享守卫 单个路由配置中 当前路由 参数校验、页面准入
组件内守卫 页面组件内部 当前组件 参数变化、离开提醒

简而言之就是:

  • 通用规则,用全局守卫

  • 单页规则,用路由独享守卫

  • 页面内部行为,用组件内守卫


八、容易混淆的点

1. 不是所有逻辑都应该写到全局守卫里

全局守卫适合放"所有页面都可能会用到"的规则。 如果某段逻辑只对一个页面有效,就应该考虑写成路由独享守卫或组件内守卫。


2. 动态路由参数变了,不代表组件一定会重新创建

例如:

  • /article/1

  • /article/2

这两个地址看起来变了,但它们可能对应的仍然是同一个组件实例。


3. next()不能忘记

在使用这类守卫时,如果仍采用next这种写法,那么就必须正确调用它。

常见情况:

  • next():放行

  • next('/login'):重定向

  • 不调用:导航可能被卡住

所以写守卫时要有明确意识:到底是放行、拦截,还是跳去别的页面。


九、常见应用场景总结

1. 登录校验

适合用全局前置守卫。

2. 动态参数校验

适合用路由独享守卫。

3. 切换同类详情页重新加载数据

适合用组件内更新守卫。

4. 离开页面前提醒

适合用组件内离开守卫。

5. 页面跳转后记录日志

适合用全局后置守卫。


十、Review

1. 全局前置守卫

TypeScript 复制代码
router.beforeEach((to, from, next) => {
  next()
})

关键词:所有路由、进入前、统一控制

2. 全局后置守卫

TypeScript 复制代码
router.afterEach((to, from) => {})

关键词:跳转后、日志、埋点

3. 路由独享守卫

TypeScript 复制代码
beforeEnter(to, from, next) {
  next()
}

关键词:单个路由专属

4. 组件内更新守卫

TypeScript 复制代码
onBeforeRouteUpdate((to, from, next) => {
  next()
})

关键词:参数变化、组件复用

5. 组件内离开守卫

TypeScript 复制代码
onBeforeRouteLeave((to, from, next) => {
  next()
})

关键词:离开页面前确认


十一、总结

路由守卫的核心不是死记它的API,而是应该先理解"它解决什么问题":

  • 全局守卫解决通用规则问题

  • 路由独享守卫解决单一路由规则问题

  • 组件内守卫解决当前页面内部过程控制问题

把这三类守卫的定位分清楚,后面无论是做登录权限、详情页参数校验,还是页面离开提醒,都会更容易上手。

总而言之,就是:

先判断这是"全局问题、单页问题,还是组件内部问题",再决定用哪一种守卫。

相关推荐
小李子呢02111 小时前
前端八股Vue---ref操作 DOM 元素或组件,调用子组件方法
前端·javascript·vue.js
Yoram1 小时前
Vue3 响应性:跨上下文的传递、转换与作用域控制
前端·vue.js
掘金安东尼1 小时前
开源小工具:掘金福利页「补签卡」按次数自动兑换(Chrome 扩展)
前端·开源
Mike_jia1 小时前
Sirius Scan:开源漏洞扫描利器,重塑企业安全防护体系
前端
知兀2 小时前
【前端】默认导出和命名导出区别
前端
XS0301062 小时前
Servlet+JQuery实现数据库数据渲染到前端页面
前端·servlet·jquery
yqcoder2 小时前
深入理解 JavaScript:什么是可迭代对象 (Iterable)?
开发语言·javascript·网络
van久2 小时前
Day27:菜单管理 + 动态路由(前端可直接用!)
前端·状态模式
恋猫de小郭2 小时前
DeepSeek V4 Flash 可以在 128GB 的 M3 Max 运行,还是 1M 上下文
前端·人工智能·ai编程