页面中间件
在页面进入前执行校验、重定向与导航控制
页面中间件用于在进入页面前执行登录校验、权限校验、参数检查、页面重定向等逻辑。它和页面文件、definePageMeta 配合使用:中间件负责导航判断,页面负责声明需要哪些中间件。
中间件是页面导航的守卫,不是请求拦截器。需要处理接口请求前后的统一逻辑时,请使用
http 提供的生命周期钩子。定义中间件
中间件文件放在项目的 src/middlewares 目录下,并通过默认导出 defineRouteMiddleware。
目录结构
src
└─ middlewares
├─ auth.global.ts
└─ permission.ts
中间件接收目标路由 to 和来源路由 from:
export default defineRouteMiddleware((to, from) => {
console.log("目标页面:", to.path);
console.log("当前页面:", from.path);
});
其中:
to表示即将进入的目标页面;from表示当前页面,可用于根据来源页面决定是否放行。
中间件类型
全局中间件
文件名以 .global 结尾的中间件会应用到所有页面,不需要在页面中声明:
src/middlewares/auth.global.ts
src/middlewares/auth.global.ts
const WHITE_LIST = ["/pages/index/index", "/pages/login/login"];
export default defineRouteMiddleware((to, from) => {
if (WHITE_LIST.includes(to.path)) {
return;
}
if (!uni.getStorageSync("token")) {
return goTo("/pages/login/login", {
replace: true,
});
}
});
全局中间件始终先于页面声明的具名中间件执行。
具名中间件
创建 src/middlewares/permission.ts:
src/middlewares/permission.ts
export default defineRouteMiddleware(async (to, from) => {
const user = await getCurrentUser();
if (!user) {
return goTo("/pages/login/login", { replace: true });
}
if (!user.hasPermission && to.path.startsWith("/pages/admin/")) {
return abortNavigation(new Error("没有访问权限"));
}
});
页面模块中通过 definePageMeta 使用:
src/pages/dashboard/index.vue
<script setup lang="ts">
definePageMeta({
middleware: "permission",
});
</script>
多个具名中间件可以使用数组,数组中的中间件会按照声明顺序执行:
<script setup lang="ts">
definePageMeta({
middleware: ["permission"],
});
</script>
页面中声明的是具名中间件名称;中间件名称由文件路径决定,不包含文件扩展名:
src/middlewares/permission.ts -> permission
src/middlewares/member/requires.ts -> member-requires
工作方式
请求进入页面时,Oiyo 会按以下顺序执行:
- 先执行所有全局中间件;
- 再按页面
definePageMeta中声明的顺序执行具名中间件; - 中间件根据返回的行为,引导当前导航放行/重定向/中止;
导航行为
放行
不返回值或返回 true,继续执行后续中间件:
export default defineRouteMiddleware(() => {
// 不返回值,放行导航
});
重定向
使用 goTo() 创建重定向结果,并通过 return 返回:
export default defineRouteMiddleware((to) => {
if (to.path !== "/pages/login/login" && !uni.getStorageSync("token")) {
return goTo("/pages/login/login");
}
});
goTo() 必须通过 return 返回。仅调用 goTo() 不会触发重定向。携带查询参数
return goTo({
path: "/pages/search/result",
query: {
keyword: "uni-app",
page: 1,
},
});
最终目标地址为:
/pages/search/result?keyword=uni-app&page=1
替换当前页面
普通页面默认使用 navigateTo。设置 replace: true 后使用 redirectTo:
return goTo("/pages/login/login", {
replace: true,
});
TabBar 页面
重定向到 TabBar 页面时会自动使用 switchTab:
return goTo("/pages/index/index");
显式指定导航方式:
return goTo("/pages/login/login", {
type: "reLaunch",
});
type 支持:
navigateToredirectToreLaunchswitchTab
重定向目标会重新执行目标页面的中间件。
中止
返回 false 或 abortNavigation(),中止当前导航:
export default defineRouteMiddleware((to) => {
if (to.path === "/pages/forbidden/index") {
return abortNavigation();
}
});
可以传入中止原因:
return abortNavigation(new Error("没有访问权限"));
中止原因会传递给导航调用的 fail 和 complete 回调。
常见场景
登录校验
src/middlewares/auth.global.ts
const WHITE_LIST = ["/pages/index/index", "/pages/login/login"];
export default defineRouteMiddleware((to) => {
if (WHITE_LIST.includes(to.path)) {
return;
}
if (!uni.getStorageSync("token")) {
return goTo("/pages/login/login", {
replace: true,
});
}
});
权限校验
src/middlewares/permission.ts
export default defineRouteMiddleware(async (to) => {
const user = await getCurrentUser();
if (!user) {
return goTo("/pages/login/login", { replace: true });
}
if (!user.hasPermission && to.path.startsWith("/pages/admin/")) {
return abortNavigation(new Error("没有访问权限"));
}
});
页面中使用:
<script setup lang="ts">
definePageMeta({
middleware: ["permission"],
});
</script>
异步中间件
中间件支持异步函数:
export default defineRouteMiddleware(async (to) => {
const user = await getCurrentUser();
if (!user && to.path !== "/pages/login/login") {
return goTo("/pages/login/login");
}
});
常见用途包括:
- 获取当前用户信息;
- 查询用户权限;
- 校验页面访问条件;
- 获取页面进入前所需的配置。