路由配置
TIP
一条路由记录描述要匹配的 URL 与要渲染的组件。会在代码中反复使用的目的地建议命名;一次性的直接跳转可使用路径。
一份实用的路由表
import { createRouter, createWebHistory } from "@elfui/router";
export const router = createRouter({
history: createWebHistory("/console"),
linkActiveClass: "nav-active",
linkExactActiveClass: "nav-exact",
routes: [
{ path: "/", name: "home", component: () => import("../pages/home-page") },
{
path: "/users/:id(\\d+)",
name: "user",
component: () => import("../pages/user-page"),
props: (route) => ({ id: Number(route.params.id) }),
meta: { requiresAuth: true, title: "用户" },
},
{ path: "/member/:id", redirect: (to) => ({ name: "user", params: to.params }) },
{ path: "/me", alias: ["/profile", "/account"], component: () => import("../pages/profile-page") },
{ path: "/:pathMatch(.*)*", name: "not-found", component: () => import("../pages/not-found-page") },
],
});WARNING
配置的 base 会包含在面向浏览器的 href 中:router.resolve({ name: "user", params: { id: 7 } }).href 会得到 /console/users/7。路由记录的 path 不需要、也不应写入 base。
参数与匹配优先级
参数会解析到 route.params。支持可选参数(?)、零到多个(*)、一个到多个(+)和自定义正则片段。
const routes = [
{ path: "/products/new", component: "product-editor" }, // 静态路由,优先匹配
{ path: "/products/:id(\\d+)", component: "product-page" },
{ path: "/docs/:sections+", component: "docs-page" }, // params.sections 是 string[]
{ path: "/search/:term?", component: "search-page" },
];TIP
静态片段的优先级高于动态片段,因此 /products/new 不会被当作 id。兜底路由应放在最后。默认匹配不区分大小写且忽略末尾斜杠;需要区分时可以开启:
createRouter({
history: createWebHistory(),
sensitive: true, // /Users 与 /users 不同
strict: true, // /users 与 /users/ 不同
routes,
});嵌套路由与元信息
子路径会与父路径拼接;匹配子路由时,route.matched 是从父到子的记录链。父级 meta 会合并到子路由,同名字段以子级为准。
{
path: "/settings",
component: () => import("../pages/settings-layout"),
meta: { requiresAuth: true },
children: [
{ path: "", name: "settings", component: () => import("../pages/settings-general") },
{ path: "security", name: "settings-security", component: () => import("../pages/settings-security") }
]
}布局页面通过 depth="1" 渲染子路由出口:
<h1>设置</h1>
<elf-router-view depth="1"></elf-router-view>Props 与命名视图
使用 props: true 直接传递路由参数。固定值可用对象;需要转换参数或 query 时可用函数。
{
path: "/reports/:year",
components: {
default: () => import("../pages/report-page"),
aside: () => import("../pages/report-filter")
},
props: {
default: route => ({ year: Number(route.params.year), mode: route.query.mode ?? "summary" }),
aside: { heading: "报表筛选" }
}
}在默认出口旁边渲染命名出口:
<section><elf-router-view></elf-router-view></section>
<aside><elf-router-view name="aside"></elf-router-view></aside>启动后添加路由
动态路由适合功能开关、插件或权限。addRoute() 会返回移除函数;同名的新路由会替换旧记录。
const removeBilling = router.addRoute({
path: "/billing",
name: "billing",
component: () => import("../pages/billing-page"),
meta: { requiresAuth: true },
});
if (router.hasRoute("billing")) {
await router.push({ name: "billing" });
}
// 后续关闭功能。
removeBilling();
// 等价的显式 API:router.removeRoute("billing")向 addRoute 传入父级名称即可添加子记录:router.addRoute("settings", { path: "billing", name: "settings-billing", component: "billing-page" })。getRoutes() 返回当前顶层记录;clearRoutes() 会移除全部记录。
恢复滚动位置
成功导航后会调用 scrollBehavior(to, from, savedPosition)。前进/后退时返回 savedPosition 以恢复位置;普通导航可返回 { top, left };{ el: "#id" } 可滚动到锚点;返回 null 则不改变滚动位置,也可以返回 Promise。
createRouter({
history: createWebHistory(),
routes,
scrollBehavior(to, _from, savedPosition) {
if (savedPosition) return savedPosition;
if (to.hash) return { el: to.hash, behavior: "smooth" };
return { top: 0, left: 0 };
},
});