路由守卫
守卫会在路由成为当前路由之前执行。守卫不返回值表示放行,返回 false 表示中止,返回字符串或命名 location 表示重定向。所有守卫都可以是异步函数。
鉴权示例
将权限策略写在路由元信息中,再使用一个全局守卫统一执行:
ts
router.beforeEach(async (to) => {
if (!to.meta.requiresAuth) return;
if (auth.session.value) return;
return {
name: "login",
query: { redirect: to.fullPath },
};
});注册函数会返回移除守卫的回调:
ts
const stopAuthGuard = router.beforeEach(checkSession);
stopAuthGuard();全局钩子
beforeEach 适合权限策略与重定向。beforeResolve 会在目标懒加载页面组件加载完成之后执行,因此适合准备页面必要的数据。afterEach 可观察成功与失败的尝试,onError 会接收抛出的错误(包括重定向循环)。
ts
router.beforeResolve(async (to) => {
if (to.name === "dashboard") await dashboardStore.load();
});
router.afterEach((to, from, failure) => {
if (!failure) analytics.page(to.fullPath, from.fullPath);
});
router.onError((error) => reportError(error));路由记录守卫
beforeEnter 只属于即将进入的记录。它可以是一个守卫,也可以是数组,适合放置该路由专有的校验。
ts
{
path: "/admin",
component: () => import("../pages/admin-page"),
beforeEnter: [requireSession, requireAdmin]
}阻止未保存修改丢失
在路由组件 setup 时调用组件守卫组合式函数。元素卸载时,它们会自动注销。
ts
import { onBeforeRouteLeave, onBeforeRouteUpdate, useRoute } from "@elfui/router";
const route = useRoute();
onBeforeRouteLeave(() => {
return form.isDirty.value ? window.confirm("放弃未保存的修改?") : true;
});
onBeforeRouteUpdate(async (to, from) => {
if (to.params.id !== from.params.id) {
await loadUser(String(to.params.id));
}
});组件守卫涵盖离开与更新。ElfUI 页面是 Custom Element,因此没有 Vue Options API 风格、接收实例参数的 beforeRouteEnter 回调。
执行顺序
一次普通导航中,守卫按以下顺序执行:
- 被停用记录的 leave 守卫,由最深层开始。
- 全局
beforeEach守卫。 - 被复用记录的 update 守卫。
- 新进入记录的
beforeEnter守卫。 - 加载目标的懒组件。
- 全局
beforeResolve守卫。 - 确认导航,然后执行
afterEach。
WARNING
返回重定向会开始一次新导航。不要让所有目标都重定向回自身;重定向循环会通过 onError 上报。
