前言
业主拎着菜走到小区门口
保安A:(突然闪现)"站住!出示健康码!"
业主:"我就住3栋啊..."
保安A:"我不管!每个进小区的都得查!(掏出清单)3栋业主...嗯,你上月物业费没交!"
业主:"???我回自己家还要被拦?"
保安A:"这是规矩!要么现在缴费,要么去物业办公室(next('/property-office'))
哈哈这个保安就是路由守卫大哥,下面是一些相关的知识点!
一、路由守卫核心知识点
1. 路由守卫作用
- 控制导航的跳转过程
- 实现权限验证、页面拦截、数据预加载
- 监控路由变化并执行逻辑
2. 守卫分类
graph TD
A[路由守卫] --> B[全局守卫]
A --> C[路由独享守卫]
A --> D[组件内守卫]
B --> B1[beforeEach]
B --> B2[beforeResolve]
B --> B3[afterEach]
C --> C1[beforeEnter]
D --> D1[beforeRouteEnter]
D --> D2[beforeRouteUpdate]
D --> D3[beforeRouteLeave]
3. 执行顺序
- 导航被触发
- 调用失活组件的
beforeRouteLeave
- 调用全局
beforeEach
- 调用路由配置的
beforeEnter
- 调用激活组件的
beforeRouteEnter
- 调用全局
beforeResolve
- 导航确认
- 调用全局
afterEach
- 触发 DOM 更新
二、代码示例
1. 全局守卫
javascript
// main.js
router.beforeEach((to, from, next) => {
// 登录验证示例
if (to.meta.requiresAuth && !isAuthenticated()) {
next('/login')
} else {
next()
}
})
/*
作用:在路由导航之前执行,通常用于进行权限验证或登录验证。
逻辑:
to.meta.requiresAuth:检查目标路由(to)是否需要身份验证。
requiresAuth 是路由元信息(meta)中的一个字段,通常用于标记哪些路由需要登录才能访问。
isAuthenticated():检查用户是否已经登录。这是一个自定义的函数,返回 true 表示用户已登录,false 表示未登录。
如果目标路由需要登录验证且用户未登录,则通过 next('/login') 将用户重定向到登录页面。
如果不需要验证或用户已登录,则调用 next() 继续导航。
*/
router.beforeResolve((to, from, next) => {
// 数据预加载示例
[] preloadData(to).then(() => next())
})
/*
作用:在路由导航被确认之前执行,通常用于在路由组件被解析之前预加载数据。
逻辑:
preloadData(to):这是一个自定义的函数,用于预加载与目标路由相关的数据。它返回一个 Promise,表示数据加载的异步操作。
当数据预加载完成后,调用 next() 继续导航。
这样可以确保在路由组件被解析之前,相关数据已经准备好,提升用户体验。
*/
router.afterEach((to, from) => {
// 页面访问统计
trackPageView(to.path)
})
/*
作用:在路由导航完成后执行,通常用于执行一些与导航相关的后续操作,如页面访问统计。
逻辑:
trackPageView(to.path):这是一个自定义的函数,用于记录用户访问的页面路径(to.path),通常用于统计页面访问量或用户行为分析。
由于 afterEach 是在导航完成后执行的,因此它不需要调用 next()。
*/
2. 路由独享守卫
javascript
// router.js
{
path: '/admin',
component: AdminPanel,
beforeEnter: (to, from, next) => {
if (user.role !== 'admin') {
next('/403')
} else {
next()
}
}
}
/*
to:目标路由对象(即将进入的路由)。
from:当前路由对象(即将离开的路由)。
next:一个函数,用于控制导航行为。
*/
3. 组件内守卫
javascript
export default {
beforeRouteEnter(to, from, next) {
// 无法访问组件实例
next(vm => {
// 通过 vm 访问组件实例
})
},
beforeRouteUpdate(to, from, next) {
// 路由参数变化时触发
this.fetchData(to.params.id)
next()
},
beforeRouteLeave(to, from, next) {
if (this.hasUnsavedChanges) {
const answer = confirm('有未保存的修改,确定离开吗?')
answer ? next() : next(false)
} else {
next()
}
}
}
三、核心参数说明
参数 | 说明 | 示例用法 |
---|---|---|
to | 目标路由对象 | to.path, to.meta |
from | 当前导航正要离开的路由对象 | from.name |
next | 控制导航行为的函数 | next(), next(false) |
四、注意事项
- 必须调用 next:每个守卫都需要执行 next()
- 异步处理:守卫可以返回 Promise
- 组件实例访问 :
beforeRouteEnter
中通过回调访问实例- 其他组件守卫可直接使用 this
- 导航取消:next(false) 中断当前导航
五、典型应用场景
- 用户认证检查
- 路由权限控制
- 数据预加载
- 页面访问统计
- 表单未保存提示
- 动态设置页面标题
六、完整示例项目结构
bash
/src
/router
index.js # 路由配置
/views
Login.vue
Admin.vue
Dashboard.vue
App.vue
main.js
七、调试技巧
- 使用
console.log
跟踪守卫执行顺序 - Vue Devtools 查看路由状态
- 通过
router.onError
捕获错误 - 使用导航故障处理:
javascript
router.push('/admin').catch(failure => {
if (failure.name === 'NavigationDuplicated') {
// 处理重复导航
}
})
路由保安,守护你的页面平安嘻嘻!