Vue Router 提供了多种 路由导航守卫,用于控制导航行为、权限校验、数据预加载等操作。导航守卫按触发时机和作用范围分类,主要有以下几类:
1. 全局守卫
这些守卫会在每次路由发生变化时触发,适合全局性的操作,比如登录状态检查、统计埋点。
1.1 beforeEach
-
触发时机:在每次路由跳转前触发。
-
使用场景:
- 校验用户是否有权限进入目标路由。
- 跳转到登录页面(如未登录)。
- 设置页面标题。
-
示例:
router.beforeEach((to, from, next) => { if (to.meta.requiresAuth && !isLoggedIn()) { next('/login'); // 未登录跳转到登录页 } else { next(); // 继续导航 } });
1.2 beforeResolve
-
触发时机:在组件内守卫(如
beforeRouteEnter
)之后,也在beforeEach
后触发。 -
使用场景:
- 确保所有异步数据加载完成后再进入路由。
- 适用于精细化控制导航。
-
示例:
router.beforeResolve((to, from, next) => { // 执行某些异步任务 loadData().then(() => { next(); // 数据加载完成后继续 }); });
1.3 afterEach
-
触发时机:路由跳转完成后触发。
-
使用场景:
- 记录页面访问统计(如 Google Analytics)。
- 复位页面状态或滚动位置。
-
示例:
router.afterEach((to, from) => { console.log(`Navigated from ${from.path} to ${to.path}`); });
2. 路由独享守卫
为某个特定路由定义守卫,直接在路由配置中设置。
beforeEnter
-
触发时机:在进入该路由之前触发。
-
使用场景:
- 针对单个路由进行权限校验。
- 加载路由特定的资源。
-
示例:
const routes = [ { path: '/dashboard', component: Dashboard, beforeEnter: (to, from, next) => { if (hasPermission()) { next(); } else { next('/login'); // 重定向 } } } ];
3. 组件内守卫
在组件内直接定义,适用于需要组件参与的路由控制。
3.1 beforeRouteEnter
-
触发时机:在路由进入之前调用。
-
特点:可以通过回调函数访问组件实例(此时组件还未创建)。
-
使用场景:
- 获取组件实例时需要访问路由相关数据。
- 页面级别的权限检查。
-
示例:
export default { beforeRouteEnter(to, from, next) { next(vm => { vm.loadData(); // 访问组件实例 }); } };
3.2 beforeRouteUpdate
-
触发时机:在当前路由改变(但仍渲染同一组件)时调用。
-
使用场景:
- 处理动态路由参数变化(如
/user/:id
)。
- 处理动态路由参数变化(如
-
示例:
export default { beforeRouteUpdate(to, from, next) { this.userId = to.params.id; // 更新组件内数据 next(); } };
3.3 beforeRouteLeave
-
触发时机:在导航离开当前路由时触发。
-
使用场景:
- 提示用户未保存的更改。
- 防止意外导航(如关闭表单页面时提示)。
-
示例:
export default { beforeRouteLeave(to, from, next) { if (this.hasUnsavedChanges) { const confirm = window.confirm('您有未保存的更改,确定要离开吗?'); if (confirm) next(); else next(false); } else { next(); } } };
总结
类型 | 守卫 | 使用场景 |
---|---|---|
全局守卫 | beforeEach | 全局权限校验、跳转控制 |
beforeResolve | 在组件守卫之前精细化控制导航 | |
afterEach | 记录日志、埋点或重置状态 | |
路由独享守卫 | beforeEnter | 特定路由的权限校验或数据加载 |
组件内守卫 | beforeRouteEnter | 异步加载数据,访问组件实例 |
beforeRouteUpdate | 动态参数更新时处理逻辑 | |
beforeRouteLeave | 离开前提醒(如未保存表单) |
完整的导航解析流程
- 导航被触发。
- 在失活的组件里调用
beforeRouteLeave
守卫。 - 调用全局的
beforeEach
守卫。 - 在重用的组件里调用
beforeRouteUpdate
守卫(2.2+)。 - 在路由配置里调用
beforeEnter
。 - 解析异步路由组件。
- 在被激活的组件里调用
beforeRouteEnter
。 - 调用全局的
beforeResolve
守卫(2.5+)。 - 导航被确认。
- 调用全局的
afterEach
钩子。 - 触发 DOM 更新。
- 调用
beforeRouteEnter
守卫中传给next
的回调函数,创建好的组件实例会作为回调函数的参数传入。