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,而是应该先理解"它解决什么问题":

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

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

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

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

总而言之,就是:

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

相关推荐
Pedantic18 小时前
SwiftUI 手势层级(Gesture Hierarchy)详解
前端
飘尘18 小时前
前端转型全栈(Java后端)的快速上手指引
前端·后端·全栈
一颗烂土豆19 小时前
Meshopt 压缩深度解析,为什么它比 Draco 更快
前端·javascript·webgl
浏览器工程师20 小时前
AI Agent 接浏览器任务,先别让它一路点到底
前端·后端
雨季mo浅忆20 小时前
VSCode自动格式化三要素
前端
爱勇宝20 小时前
深扒 Anthropic 1680 位工程师简历:应届生几乎没机会,AI 公司最缺的不是博士
前端·后端·程序员
kyriewen21 小时前
同事每天催我 Code Review,我写了个脚本让 AI 替我 review PR——现在他反过来催 AI 了
前端·javascript·ai编程
user20585561518131 天前
Windows 项目安装时报 `node-sass` 错误,如何快速处理
前端
LiaCode1 天前
Redis 在生产项目的使用
前端·后端