一、导航守卫的分类(高频考点)
Vue-router的导航守卫主要分为三类,按作用范围和触发时机排序:
1. 全局守卫(应用级别)
- 全局前置守卫:
router.beforeEach- 每次路由跳转前触发,用于登录验证、权限检查。
- 全局解析守卫:
router.beforeResolve- 路由组件被解析后触发,用于获取数据或进度条收尾。
- 全局后置钩子:
router.afterEach- 路由跳转完成后触发,用于页面统计、修改document.title。
2. 路由独享守卫(单个路由配置)
beforeEnter- 只在进入特定路由时触发,配置在路由对象中。
3. 组件内守卫(组件级别)
beforeRouteEnter- 进入组件前触发,此时组件实例尚未创建。
beforeRouteUpdate- 路由参数变化时触发(如从
/user/1到/user/2)。
- 路由参数变化时触发(如从
beforeRouteLeave- 离开组件时触发,常用于阻止用户意外离开(如未保存表单)。
二、执行流程(关键理解)
导航守卫的完整执行顺序:
- 导航被触发(如点击链接、调用
router.push)。 - 前置守卫链按顺序执行:
- 全局
beforeEach→ 路由独享beforeEnter→ 组件内beforeRouteEnter。
- 全局
- 路由组件被解析(异步组件加载完成)。
- 全局解析守卫
beforeResolve执行。 - 导航确认(此时路由已跳转)。
- 全局后置钩子
afterEach执行。 - 触发DOM更新。
- 组件内
beforeRouteUpdate(若路由参数变化)。
三、典型应用场景(结合项目经验)
1. 登录验证
router.beforeEach((to, from, next) => {
if (to.meta.requiresAuth && !isAuthenticated()) {
next('/login'); // 未登录时重定向到登录页
} else {
next(); // 继续导航
}
});
2. 权限控制
router.beforeEach((to, from, next) => {
if (to.meta.role === 'admin' && !currentUser.isAdmin) {
next('/forbidden'); // 无权限时重定向
} else {
next();
}
});
3. 路由切换动画
// 全局前置守卫设置过渡效果
router.beforeEach((to, from, next) => {
document.body.classList.add('page-loading');
next();
});
// 全局后置钩子移除过渡效果
router.afterEach(() => {
setTimeout(() => {
document.body.classList.remove('page-loading');
}, 300);
});
4. 阻止未保存表单离开
export default {
beforeRouteLeave(to, from, next) {
if (this.formDirty) { // 表单已修改但未提交
if (confirm('确认离开?未保存的内容将丢失。')) {
next(); // 允许离开
} else {
next(false); // 取消导航
}
} else {
next();
}
}
};
四、实现细节与注意事项(高频陷阱)
1. next()的正确用法
- 必须调用:每个守卫都必须调用
next()来 resolve 钩子,否则导航会被挂起。 - 禁止多次调用:
next()只能调用一次,多次调用会导致警告。 - 参数含义:
next():继续正常导航;next(false):取消当前导航;next('/path')或next({ path: '/path' }):重定向到指定路径。
2. 组件内守卫的特殊性
beforeRouteEnter中无法访问this(组件实例尚未创建),需通过next(vm => {})访问:beforeRouteEnter(to, from, next) { next(vm => { // 通过vm访问组件实例 console.log(vm.$data); }); }
3. 异步操作处理
- 若守卫中存在异步操作(如API请求),需等待异步完成后再调用
next():router.beforeEach(async (to, from, next) => { const user = await fetchUser(); if (user.isAdmin) { next(); } else { next('/login'); } });
五、总结
“Vue-router的导航守卫是控制路由访问和生命周期的核心机制,主要分为:
- 全局守卫:应用级别拦截(如登录验证);
- 路由独享守卫:单个路由配置(如特定页面权限);
- 组件内守卫:组件级别控制(如阻止未保存表单离开)。
其执行流程是一个链式调用,从全局到路由再到组件,最终通过next()方法决定导航结果。在实际项目中,我会用全局前置守卫处理登录态,用组件内守卫优化用户体验,并注意避免next()的误用导致导航异常。”