Vue Router 导航钩子函数详解 | 路由守卫使用指南

Vue Router 提供了多种导航钩子函数(也称为导航守卫),这些钩子函数允许你在路由导航过程中执行一些逻辑,例如权限验证、数据预取等。以下是 Vue Router 的主要钩子函数:
1. 全局前置守卫 (beforeEach
)
- 调用时机: 在路由导航开始之前调用。
- 用途: 常用于权限验证、全局拦截等。
- 参数:
to
: 即将进入的目标路由对象。from
: 当前导航正要离开的路由对象。next
: 必须调用此函数来 resolve 这个钩子。next()
表示继续导航,next(false)
表示中断当前导航,next('/path')
或next({ path: '/' })
表示跳转到不同的路径。
router.beforeEach((to, from, next) => {
if (to.meta.requiresAuth && !isAuthenticated()) {
next('/login');
} else {
next();
}
});
2. 全局解析守卫 (beforeResolve
)
- 调用时机: 在导航被确认之前,同时在所有组件内守卫和异步路由组件被解析之后调用。
- 用途: 适合用于在导航被确认之前执行一些逻辑,例如数据预取。
router.beforeResolve((to, from, next) => {
// 执行一些逻辑
next();
});
3. 全局后置钩子 (afterEach
)
- 调用时机: 在导航完成后调用。
- 用途: 常用于日志记录、页面滚动到顶部等操作。
- 注意: 这个钩子没有
next
函数,也不会影响导航。
router.afterEach((to, from) => {
// 例如记录页面访问
logPageView(to.path);
});
4. 路由独享的守卫 (beforeEnter
)
- 调用时机: 在进入特定路由之前调用。
- 用途: 适用于某个特定路由的权限验证或数据预取。
const routes = [
{
path: '/dashboard',
component: Dashboard,
beforeEnter: (to, from, next) => {
if (!isAuthenticated()) {
next('/login');
} else {
next();
}
}
}
];
5. 组件内的守卫
beforeRouteEnter
: 在渲染该组件的对应路由被确认前调用。此时组件实例还未被创建,因此无法访问this
。beforeRouteUpdate
: 在当前路由改变,但是该组件被复用时调用。例如,对于一个带有动态参数的路径/user/:id
,在/user/1
和/user/2
之间跳转时,组件会被复用,此时会调用beforeRouteUpdate
。beforeRouteLeave
: 在导航离开该组件的对应路由时调用。常用于提示用户保存未保存的更改。
export default {
beforeRouteEnter(to, from, next) {
// 无法访问 `this`
next(vm => {
// 通过 `vm` 访问组件实例
});
},
beforeRouteUpdate(to, from, next) {
// 可以访问 `this`
this.name = to.params.name;
next();
},
beforeRouteLeave(to, from, next) {
const answer = window.confirm('Do you really want to leave?');
if (answer) {
next();
} else {
next(false);
}
}
};
6. 完整的导航解析流程
- 导航被触发。
- 在失活的组件里调用
beforeRouteLeave
守卫。 - 调用全局的
beforeEach
守卫。 - 在重用的组件里调用
beforeRouteUpdate
守卫。 - 在路由配置里调用
beforeEnter
。 - 解析异步路由组件。
- 在被激活的组件里调用
beforeRouteEnter
。 - 调用全局的
beforeResolve
守卫。 - 导航被确认。
- 调用全局的
afterEach
钩子。 - 触发 DOM 更新。
- 调用
beforeRouteEnter
守卫中传给next
的回调函数,创建好的组件实例会作为回调函数的参数传入。
7. 注意事项
next
函数: 在beforeEach
、beforeResolve
、beforeEnter
、beforeRouteEnter
和beforeRouteUpdate
中,必须调用next
函数来继续导航。如果不调用next
,导航将不会继续。- 异步操作: 钩子函数中可以执行异步操作,例如 API 请求,但需要确保在异步操作完成后调用
next
。
8. 示例:权限验证
router.beforeEach((to, from, next) => {
if (to.meta.requiresAuth && !isAuthenticated()) {
next('/login');
} else {
next();
}
});
9. 示例:页面滚动到顶部
router.afterEach((to, from) => {
window.scrollTo(0, 0);
});
10. 示例:数据预取
router.beforeResolve((to, from, next) => {
if (to.meta.requiresFetch) {
fetchData().then(() => {
next();
});
} else {
next();
}
});
通过合理使用这些钩子函数,你可以更好地控制路由导航过程,确保应用的逻辑和用户体验得到优化。