Vue3 路由守卫详解:全局守卫、路由独享守卫、组件内守卫
一、前言
在Vue3开发中,路由守卫是一个非常重要的知识点。很多常见需求都离不开它,比如:
页面权限控制
登录校验
动态路由参数校验
页面离开提醒
路由切换时执行额外逻辑
路由守卫本质上就是:在路由跳转的不同阶段,执行指定逻辑,对跳转过程进行控制。
本文重点整理三类最常用的守卫:
全局路由守卫
路由独享守卫
组件内守卫
尽量聚焦在“是什么、怎么用、有什么作用”
二、什么是路由守卫
路由守卫可以理解为一种“拦截机制”。
当用户准备从一个页面跳转到另一个页面时,Vue Router 会在跳转前、跳转后,或者组件更新过程中,给我们一些可以插入逻辑的时机。我们可以在这些时机中:
放行跳转
拦截跳转
重定向到其他页面
执行提示、日志、校验等逻辑
简单说,路由守卫解决的是:
页面不是想进就进,也不是想走就走,而是先经过规则判断。
三、路由守卫的分类
Vue Router 中常见的路由守卫主要有三类:
1. 全局守卫
对所有路由都生效,适合处理整个项目通用的逻辑。
2. 路由独享守卫
只对某一个具体路由生效,适合处理该路由特有的逻辑。
3. 组件内守卫
写在页面组件内部,适合处理和当前组件强相关的逻辑。
可以先记住一句话:
全局守卫管整体,独享守卫管单个路由,组件内守卫管当前页面组件。
四、全局路由守卫
1. 什么是全局前置守卫
全局前置守卫会在每次路由跳转前执行,常用写法如下:
router.beforeEach((to, from, next) => { next() })参数说明:
to:准备进入的目标路由
from:当前离开的路由
next:控制是否继续跳转
它最常见的作用就是:
登录校验
权限控制
根据路由信息做统一判断
2. 全局前置守卫的典型用法
一个很常见的场景是:某些页面必须登录后才能访问。
示例:
router.beforeEach((to, from, next) => { if (to.meta.login) { const token = localStorage.getItem('token') if (!token) { next('/login') return } } next() })这段代码的逻辑是:
每次跳转前先进入守卫
判断目标路由是否需要登录
如果需要登录,就去本地检查token
没有token就跳转到登录页
有token就正常放行
这里的重点不是代码本身,而是理解这种设计思路:
把通用的权限判断统一放到全局前置守卫里处理。
3.meta的作用
在做权限控制时,通常会结合路由元信息meta一起使用,例如:
{ path: '/admin', name: 'admin', component: Admin, meta: { login: true, title: '后台管理' } }这里的meta可以理解为:给路由额外附加的自定义信息。
例如:
login:true 表示这个页面需要登录
title:可以用来设置页面标题
好处是:
规则和路由配置写在一起,结构清晰
全局守卫可以统一读取这些信息
后期扩展角色权限也比较方便
4. 全局后置守卫
全局后置守卫会在路由跳转完成后执行,写法如下:
router.afterEach((to, from) => { console.log('路由跳转完成') })它的常见用途有:
记录日志
页面埋点统计
修改文档标题
注意两点:
afterEach没有next
它不能阻止跳转
所以它更适合做“跳转完成之后的附加处理”。
五、路由独享守卫
1. 什么是路由独享守卫
路由独享守卫是只对某个路由生效的守卫,直接写在路由配置对象中,常用写法如下:
{ path: '/article/:id', name: 'article', component: Article, beforeEnter(to, from, next) { next() } }它适合处理某一个页面自己的进入规则,而不是整个项目的通用规则。
2. 路由独享守卫的典型作用
最常见的用途之一就是:进入页面前先校验路由参数。
例如文章详情页通常会写成:
{ 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 写法是:
onBeforeRouteUpdateonBeforeRouteLeave
1. onBeforeUpdate的作用
它会在当前路由更新,但组件被复用时触发。
示例:
import { onBeforeRouteUpdate } from 'vue-router' onBeforeRouteUpdate((to, from, next) => { console.log('路由参数变化时触发') next() })这个守卫特别适合详情页场景。
比如当前在:
/article/1然后跳转到:
/article/2这时很多情况下并不会重新创建一个新组件,而是复用原来的组件实例。也就是说,虽然地址变了,但页面组件还是同一个。
这时候如果你只在组件初次加载时处理数据,很可能拿不到更新后的参数,因此就需要onBeforeRouteUpdate。
它的作用可以概括为:
监听同一组件下的路由变化
在参数变化时重新处理逻辑
适合重新请求详情数据
2. onBeforeRouteLeave的作用
它会在当前组件对应的路由即将离开时触发。
示例:
import { onBeforeRouteLeave } from 'vue-router' onBeforeRouteLeave((to, from, next) => { console.log('路由离开时触发') next() })它常见的作用有:
离开表单页前提醒用户
未保存内容时阻止离开
离开页面前做一些清理工作
例如:
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. 全局前置守卫
router.beforeEach((to, from, next) => { next() })关键词:所有路由、进入前、统一控制
2. 全局后置守卫
router.afterEach((to, from) => {})关键词:跳转后、日志、埋点
3. 路由独享守卫
beforeEnter(to, from, next) { next() }关键词:单个路由专属
4. 组件内更新守卫
onBeforeRouteUpdate((to, from, next) => { next() })关键词:参数变化、组件复用
5. 组件内离开守卫
onBeforeRouteLeave((to, from, next) => { next() })关键词:离开页面前确认
十一、总结
路由守卫的核心不是死记它的API,而是应该先理解“它解决什么问题”:
全局守卫解决通用规则问题
路由独享守卫解决单一路由规则问题
组件内守卫解决当前页面内部过程控制问题
把这三类守卫的定位分清楚,后面无论是做登录权限、详情页参数校验,还是页面离开提醒,都会更容易上手。
总而言之,就是:
先判断这是“全局问题、单页问题,还是组件内部问题”,再决定用哪一种守卫。
