路由守卫是Vue Router中控制导航流程的核心机制。当用户在页面间跳转时,守卫函数会在特定时机触发,实现权限校验、数据预载、埋点上报等关键逻辑。本文结合企业级项目实践,系统解析全局守卫原理、配置规范及典型应用场景,附可直接复用的代码方案。
一、路由守卫核心机制解析
本质:导航过程中触发的钩子函数,按执行时机分为三类:
beforeEach:导航触发时(解析异步路由前)beforeResolve:所有组件内守卫及异步路由解析完成后afterEach:导航确认完成后(不可中断导航)
关键参数说明(以beforeEach为例):
router.beforeEach((to, from, next) => {
// to: 即将进入的目标路由对象
// from: 当前导航正要离开的路由
// next: 必须调用!控制导航行为
// next() → 放行
// next(false) → 中断导航
// next('/login') → 重定向
// next(error) → 触发onError
})
⚠️ 重要原则:next函数必须且仅调用一次,否则导航将永久挂起。异步操作中需确保所有分支均调用next。
二、企业级项目实战配置
场景1:权限验证与动态路由
// router/index.js
router.beforeEach(async (to, from, next) => {
const token = localStorage.getItem('auth_token');
const hasPermission = store.getters.roles?.length > 0;
// 白名单路由(登录页、404等)
const whiteList = ['/login', '/403'];
if (whiteList.includes(to.path)) return next();
if (!token) {
return next({ path: '/login', query: { redirect: to.fullPath } });
}
if (!hasPermission) {
try {
// 动态获取用户权限并生成路由
await store.dispatch('user/getUserInfo');
const accessRoutes = await store.dispatch('permission/generateRoutes');
accessRoutes.forEach(route => router.addRoute(route));
return next({ ...to, replace: true }); // 重试当前导航
} catch (error) {
await store.dispatch('user/resetToken');
next(`/login?redirect=${to.path}`);
}
}
next();
});
效果:未登录用户自动跳转登录页;已登录用户首次访问时动态注入权限路由,避免菜单与路由不匹配。
场景2:全局加载进度与埋点
// 引入NProgress(需安装nprogress包)
import NProgress from 'nprogress';
import 'nprogress/nprogress.css';
router.beforeEach((to, from, next) => {
NProgress.start();
// 页面访问埋点(示例)
if (window._hmt) {
window._hmt.push(['_trackPageview', to.fullPath]);
}
next();
});
router.afterEach(() => {
NProgress.done();
// 动态设置页面标题
document.title = to.meta.title || '默认标题';
});
价值:
- 用户感知加载状态,降低跳出率
- 精准统计页面访问路径,支撑运营分析
- SEO友好:服务端渲染项目中可结合metaInfo动态设置title/description
三、高频问题避坑指南
| 问题现象 | 根本原因 | 解决方案 |
|---|---|---|
| 页面卡在加载中 | next()未调用或多次调用 |
使用try/catch确保所有分支调用next;异步操作加finally |
| 路由重复跳转 | 守卫内重定向未校验目标路径 | 添加if (to.path === '/login') return next();防循环 |
| 动态路由刷新404 | 刷新后路由表重置 | 将权限路由持久化至localStorage,刷新时重新addRoute |
| 守卫执行顺序混乱 | 混用全局/路由独享/组件内守卫 | 明确执行链:全局beforeEach → 路由独享beforeEnter → 组件beforeRouteEnter → 全局beforeResolve → 全局afterEach |
四、最佳实践建议
- 守卫职责单一化:权限校验、埋点、进度条分守卫处理,避免单函数过长
- 异步操作超时控制:关键接口(如权限获取)设置Promise.race超时兜底
- 错误边界处理:全局注册
router.onError捕获路由解析异常 - 性能考量:避免在守卫中执行重型计算,必要时使用Web Worker
路由守卫是前端安全与体验的“守门人”。合理设计守卫逻辑,既能保障业务安全,又能提升用户流转体验。建议将守卫配置纳入代码审查清单,结合单元测试验证关键路径(如无token跳转、权限拦截等)。