面包屑导航
修改app.tsx文件
tsx
// 运行时配置
import routes from "@/config/routes";
import mockMenuData from "@/mock/data";
type RouteConfig = {
path?: string;
name?: string;
routes?: RouteConfig[];
};
// 从路由配置中递归提取 路径 -> 菜单名称 映射
function buildMenuNameMap(routes: RouteConfig[] = []): Record<string, string> {
const map: Record<string, string> = {};
routes.forEach((route) => {
if (route.path && route.name) {
map[route.path.replace(/^\//, "")] = route.name.trim();
}
if (route.routes) {
Object.assign(map, buildMenuNameMap(route.routes));
}
});
return map;
}
const menuNameMap = buildMenuNameMap(routes as RouteConfig[]);
// 收集所有"有子路由"的路径(来自路由配置),用于面包屑判断
const parentPaths = new Set<string>();
(function collectParents(list: RouteConfig[] = []) {
list.forEach((r) => {
if (r.routes && r.routes.length > 0 && r.path) {
parentPaths.add(r.path);
collectParents(r.routes);
}
});
})(routes as RouteConfig[]);
type MenuItem = {
path: string;
name: string;
children?: MenuItem[];
};
// 将平铺的路径数组转换为菜单树
function buildMenu(paths: string[]): MenuItem[] {
const root: MenuItem[] = [];
const nodeMap = new Map<string, MenuItem>();
paths.forEach((p) => {
const segments = p.split("/");
let parentChildren = root;
let currentPath = "";
segments.forEach((seg, idx) => {
currentPath = currentPath ? `${currentPath}/${seg}` : seg;
let node = nodeMap.get(currentPath);
if (!node) {
node = {
path: `/${currentPath}`,
name: menuNameMap[currentPath] || seg,
};
nodeMap.set(currentPath, node);
parentChildren.push(node);
}
if (idx < segments.length - 1) {
node.children = node.children || [];
parentChildren = node.children;
}
});
});
return root;
}
// 全局初始化数据配置,用于 Layout 用户信息和权限初始化
// 更多信息见文档:https://umijs.org/docs/api/runtime-config#getinitialstate
export async function getInitialState(): Promise<{ name: string }> {
return { name: "@umijs/max" };
}
export const layout = () => {
return {
logo: "https://img.alicdn.com/tfs/TB1YHEpwUT1gK0jSZFhXXaAtVXa-28-27.svg",
menu: {
locale: false,
// 从 mock 数据动态生成菜单
request: async () => buildMenu(mockMenuData),
},
// 开启面包屑导航
breadcrumbRender: (routers = []) => {
return [
{
path: "/home",
breadcrumbName: "首页",
},
...routers,
];
},
// 自定义面包屑项渲染:路径属于父路由(有子路由)时渲染为纯文本
itemRender: (route: any) => {
const isParent = route.path && parentPaths.has(route.path);
return isParent ? (
<span>{route.breadcrumbName}</span>
) : (
<a href={route.path}>{route.breadcrumbName}</a>
);
},
};
};