Vue导航守卫学习

📅 2026/7/7 5:29:54 👁️ 阅读次数 📝 编程学习
Vue导航守卫学习

Vue 导航守卫(Navigation Guards)学习文档

适用版本:Vue Router 3.x(Vue 2)/ Vue Router 4.x(Vue 3,语法略有差异)

一、什么是导航守卫

导航守卫是 Vue Router 提供的路由跳转过程中的钩子函数,主要用于:

  • 登录鉴权 / 权限校验
  • 页面标题(document.title)设置
  • 数据预取
  • 阻止或重定向非法跳转
  • 埋点、离开确认等

它们会在路由发生变化时按固定顺序依次触发


二、三大分类

1. 全局守卫(定义在router实例上)

constrouter=newVueRouter({routes})// ① 前置守卫:最常用,登录校验主战场router.beforeEach((to,from,next)=>{// to: 目标路由// from: 离开的路由// next: 放行函数(必须调用,否则路由停滞)next()})// ② 解析守卫:在组件内守卫和异步路由组件被解析之后触发router.beforeResolve((to,from,next)=>{next()})// ③ 后置钩子:导航已完成,无 next,常用于埋点、滚动复位router.afterEach((to,from)=>{window.scrollTo(0,0)})

2. 路由独享守卫(定义在路由配置里)

{path:'/settlement',component:Settlement,beforeEnter:(to,from,next)=>{// 仅对当前路由生效next()}}

3. 组件内守卫(定义在组件选项里)

exportdefault{// ⚠️ 此时组件实例尚未创建,拿不到 thisbeforeRouteEnter(to,from,next){next(vm=>{// 通过回调访问实例(唯一的特例)})},// 当前路由改变、但组件复用时触发(如 /user/1 → /user/2)beforeRouteUpdate(to,from,next){this.fetchData(to.params.id)next()},// 离开时触发,this 可用,常用于「未保存提示」beforeRouteLeave(to,from,next){if(this.formDirty&&!confirm('有未保存内容,确定离开?')){next(false)// 取消导航}else{next()}}}

三、next()的用法

调用方式含义
next()放行,继续跳转到to
next(false)中断,回到当前页(from
next('/login')重定向到指定路径
next(new Error(...))触发router.onError
next(vm => {...})beforeRouteEnter可用

Vue Router 4 (Vue 3)中改为return语义:return true / false / '/login',不再强制next


四、完整的导航解析顺序(重点)

一次跳转会按以下顺序触发:

1. 导航被触发 2. 在失活组件里调用 beforeRouteLeave 3. 调用全局 beforeEach 4. 在重用组件里调用 beforeRouteUpdate 5. 调用路由配置里的 beforeEnter 6. 解析异步路由组件 7. 在被激活组件里调用 beforeRouteEnter 8. 调用全局 beforeResolve 9. 导航被确认 10. 调用全局 afterEach 11. 触发 DOM 更新 12. 调用 beforeRouteEnter 中 next 传入的回调

记忆口诀:「离开 → 全局前置 → 复用更新 → 独享 → 解析组件 → 进入 → 全局解析 → 确认 → 全局后置」


五、实战:登录鉴权(典型场景)

使用token标记需要登录的路由,可在router/index.js这样实现:

import{getToken}from'@/utils/auth'// 从 Cookie 读取 USER_TOKENconstWHITE_LIST=['/login','/register','/403']router.beforeEach((to,from,next)=>{// 1. 设置页面标题document.title=to.meta.tabTitle||'资环链金智慧平台'consthasToken=getToken()if(hasToken){if(to.path==='/login'){next({path:'/'})// 已登录则拦截登录页}else{next()// 正常放行}}else{// 白名单放行,其余统一跳登录并带上 redirectWHITE_LIST.includes(to.path)?next():next(`/login?redirect=${encodeURIComponent(to.fullPath)}`)}})

六、常见坑位

  1. 忘记调用next()→ 页面卡住、白屏,最经典的错误。
  2. 死循环beforeEach里重定向到自己(如已登录又next('/login')),需加条件分支。
  3. 异步校验:鉴权接口需await后再next(),否则拿不到结果就放行了。
  4. beforeRouteEnter拿不到this:必须用next(vm => {...})回调。
  5. 组件复用不触发created:参数变化(/detail/1/detail/2)只触发beforeRouteUpdate,需在此重新请求数据,或在<router-view :key="$route.fullPath">强制重建。

七、速查表

守卫位置是否能取消跳转典型用途
beforeEach全局登录/权限校验
beforeResolve全局数据预加载完成后处理
afterEach全局标题、滚动、埋点
beforeEnter路由单路由鉴权
beforeRouteEnter组件进入前数据校验
beforeRouteUpdate组件动态参数变化
beforeRouteLeave组件离开确认/防误操作

八、Vue 3 补充(Composition API)

<script setup>中可用专用钩子:

<script setup> import { onBeforeRouteLeave, onBeforeRouteUpdate } from 'vue-router' onBeforeRouteLeave((to, from) => { const answer = window.confirm('确定离开吗?') if (!answer) return false // 取消导航 }) onBeforeRouteUpdate((to, from) => { // 路由参数变化时触发 fetchData(to.params.id) }) </script>

注意:Vue 3 中没有onBeforeRouteEnter,进入前逻辑需通过beforeEnter路由独享守卫或在组件setup中直接处理。