路由工具
概述
本文档介绍了一组用于处理路由和菜单数据的实用工具函数。这些函数主要用于处理嵌套菜单结构,实现常见的路由操作,如过滤当前路由、扁平化处理、获取面包屑导航等功能。
数据结构定义
这些函数基于以下菜单数据结构:
typescript
// 菜单选项接口示例 (Menu.MenuOptions)
interface MenuOptions {
path: string; // 路由路径
name?: string; // 路由名称
component?: any; // 组件
redirect?: string; // 重定向地址
meta: {
title?: string; // 菜单标题
icon?: string; // 菜单图标
isHide?: boolean; // 是否在菜单中隐藏
isKeepAlive?: boolean;// 是否需要缓存
[key: string]: any; // 其他元数据
};
children?: MenuOptions[]; // 子菜单
[key: string]: any; // 其他属性
}函数详解
1. 过滤当前路由 - filterCurrentRoute
根据当前访问的路径,从菜单列表中查找并返回匹配的路由对象。
函数签名
typescript
function filterCurrentRoute(menuList: Menu.MenuOptions[], path: string): Menu.MenuOptions参数
menuList: 菜单列表数组path: 当前访问的路径
返回值
返回与当前路径匹配的路由对象,如果没有找到则返回空对象。
示例
javascript
// 输入数据
const menuList = [
{
path: '/dashboard',
meta: { title: '仪表盘' },
children: [
{ path: '/dashboard/analysis', meta: { title: '分析页' } }
]
},
{ path: '/profile', meta: { title: '个人页' } }
];
// 查找当前路由
const currentRoute = filterCurrentRoute(menuList, '/dashboard/analysis');
console.log(currentRoute);
// 输出: { path: '/dashboard/analysis', meta: { title: '分析页' } }2. 扁平化菜单数组 - getFlatArr
将嵌套的菜单数组结构扁平化为一维数组。
函数签名
typescript
function getFlatArr(menulist: Menu.MenuOptions[]): Menu.MenuOptions[]参数
menulist: 嵌套结构的菜单列表数组
返回值
返回扁平化后的菜单数组,包含原始列表中的所有菜单项。
示例
javascript
// 输入数据
const menuList = [
{
path: '/dashboard',
meta: { title: '仪表盘' },
children: [
{ path: '/dashboard/analysis', meta: { title: '分析页' } }
]
},
{ path: '/profile', meta: { title: '个人页' } }
];
// 扁平化处理
const flatMenuList = getFlatArr(menuList);
console.log(flatMenuList);
/* 输出:
[
{
path: '/dashboard',
meta: { title: '仪表盘' },
children: [...]
},
{ path: '/dashboard/analysis', meta: { title: '分析页' } },
{ path: '/profile', meta: { title: '个人页' } }
]
*/3. 获取需要缓存的路由名称 - getKeepAliveRouterName
使用递归方式,过滤出需要被 keep-alive 缓存的路由名称。
函数签名
typescript
function getKeepAliveRouterName(
menuList: Menu.MenuOptions[],
keepAliveArr: string[] = []
): string[]参数
menuList: 菜单列表数组keepAliveArr: 可选,用于存储缓存路由名称的数组
返回值
返回需要被缓存的路由名称数组。
示例
javascript
// 输入数据
const menuList = [
{
path: '/dashboard',
name: 'Dashboard',
meta: { isKeepAlive: true, title: '仪表盘' },
children: [
{
path: '/dashboard/analysis',
name: 'Analysis',
meta: { isKeepAlive: false, title: '分析页' }
}
]
},
{
path: '/profile',
name: 'Profile',
meta: { isKeepAlive: true, title: '个人页' }
}
];
// 获取需要缓存的路由名称
const cacheNames = getKeepAliveRouterName(menuList);
console.log(cacheNames);
// 输出: ['Dashboard', 'Profile']4. 获取可显示的菜单列表 - getShowMenuList
过滤出需要在菜单中显示的路由列表,移除 meta.isHide 为 true 的项。
函数签名
typescript
function getShowMenuList(menuList: Menu.MenuOptions[]): Menu.MenuOptions[]参数
menuList: 完整的菜单列表数组
返回值
返回过滤后的菜单列表,仅包含应该显示的菜单项。
示例
javascript
// 输入数据
const menuList = [
{
path: '/dashboard',
meta: { title: '仪表盘' },
children: [
{ path: '/dashboard/analysis', meta: { title: '分析页' } },
{ path: '/dashboard/monitor', meta: { isHide: true, title: '监控页' } }
]
},
{ path: '/profile', meta: { title: '个人页' } },
{ path: '/system', meta: { isHide: true, title: '系统设置' } }
];
// 获取要显示的菜单列表
const showMenuList = getShowMenuList(menuList);
console.log(showMenuList);
/* 输出:
[
{
path: '/dashboard',
meta: { title: '仪表盘' },
children: [
{ path: '/dashboard/analysis', meta: { title: '分析页' } }
]
},
{ path: '/profile', meta: { title: '个人页' } }
]
*/5. 获取菜单路径列表 - getMenuListPath
从菜单列表中提取所有路径,生成一维数组,常用于路由鉴权。
函数签名
typescript
function getMenuListPath(
menuList: Menu.MenuOptions[],
menuPathArr: string[] = []
): string[]参数
menuList: 菜单列表数组menuPathArr: 可选,用于存储路径的数组
返回值
返回包含所有菜单路径的一维字符串数组。
示例
javascript
// 输入数据
const menuList = [
{
path: '/dashboard',
children: [
{ path: '/dashboard/analysis' },
{ path: '/dashboard/monitor' }
]
},
{ path: '/profile' }
];
// 获取所有菜单路径
const pathList = getMenuListPath(menuList);
console.log(pathList);
// 输出: ['/dashboard', '/dashboard/analysis', '/dashboard/monitor', '/profile']6. 获取当前路径的面包屑 - getCurrentBreadcrumb
根据当前路径,从菜单列表中递归查找匹配的面包屑路径。
函数签名
typescript
function getCurrentBreadcrumb(
path: string,
menuList: Menu.MenuOptions[]
): Menu.MenuOptions[]参数
path: 当前访问的路径menuList: 菜单列表数组
返回值
返回当前路径对应的面包屑导航数组,按层级顺序排列。
示例
javascript
// 输入数据
const menuList = [
{
path: '/dashboard',
meta: { title: '仪表盘' },
children: [
{
path: '/dashboard/analysis',
meta: { title: '分析页' }
}
]
},
{ path: '/profile', meta: { title: '个人页' } }
];
// 获取面包屑导航
const breadcrumb = getCurrentBreadcrumb('/dashboard/analysis', menuList);
console.log(breadcrumb);
/* 输出:
[
{ path: '/dashboard', meta: { title: '仪表盘' }, children: [...] },
{ path: '/dashboard/analysis', meta: { title: '分析页' } }
]
*/7. 获取所有面包屑列表 - getAllBreadcrumbList
预先计算所有可能的面包屑路径,生成以路径为键的对象,常用于存储到全局状态管理中。
函数签名
typescript
function getAllBreadcrumbList(menuList: Menu.MenuOptions[]): { [key: string]: Menu.MenuOptions[] }参数
menuList: 菜单列表数组
返回值
返回一个对象,其中键是路径,值是对应的面包屑导航数组。
示例
javascript
// 输入数据
const menuList = [
{
path: '/dashboard',
meta: { title: '仪表盘' },
children: [
{ path: '/dashboard/analysis', meta: { title: '分析页' } }
]
},
{ path: '/profile', meta: { title: '个人页' } }
];
// 获取所有面包屑路径
const allBreadcrumbs = getAllBreadcrumbList(menuList);
console.log(allBreadcrumbs);
/* 输出:
{
'/dashboard/analysis': [
{ path: '/dashboard', meta: { title: '仪表盘' }, children: [...] },
{ path: '/dashboard/analysis', meta: { title: '分析页' } }
],
'/profile': [
{ path: '/profile', meta: { title: '个人页' } }
]
}
*/8. 格式化权限菜单数据 - formatMenuData
将后端返回的菜单数据格式化为前端路由所需的结构。
函数签名
typescript
function formatMenuData(list: any[]): Menu.MenuOptions[]参数
list: 后端返回的原始菜单数据数组
返回值
返回格式化后的菜单数组,符合路由配置要求。
示例
javascript
// 输入数据 (后端格式)
const backendMenuList = [
{
id: 'dashboard',
name: '仪表盘',
url: '/dashboard',
icon: 'dashboard-icon',
config: {
props: { transition: 'fade' },
redirect: '/dashboard/analysis'
},
children: [
{
id: 'analysis',
name: '分析页',
url: '/dashboard/analysis',
icon: 'analysis-icon',
config: {}
}
]
}
];
// 格式化为前端路由格式
const formattedMenu = formatMenuData(backendMenuList);
console.log(formattedMenu);
/* 输出:
[
{
path: '/dashboard',
title: '仪表盘',
name: 'dashboard',
meta: {
icon: 'dashboard-icon',
title: '仪表盘'
},
redirect: '/dashboard/analysis',
props: { transition: 'fade' },
children: [
{
path: '/dashboard/analysis',
title: '分析页',
name: 'analysis',
meta: {
icon: 'analysis-icon',
title: '分析页'
}
}
]
}
]
*/9. 扁平化菜单列表 - getFlatMenuList
将嵌套菜单扁平化处理,主要用于添加动态路由,与 getFlatArr 类似但使用了不同的实现方式。
函数签名
typescript
function getFlatMenuList(menuList: Menu.MenuOptions[]): Menu.MenuOptions[]参数
menuList: 嵌套结构的菜单列表数组
返回值
返回扁平化后的菜单数组,包含原始列表中的所有菜单项。
示例
javascript
// 输入数据
const menuList = [
{
path: '/dashboard',
meta: { title: '仪表盘' },
children: [
{ path: '/dashboard/analysis', meta: { title: '分析页' } }
]
},
{ path: '/profile', meta: { title: '个人页' } }
];
// 扁平化处理
const flatMenuList = getFlatMenuList(menuList);
console.log(flatMenuList);
/* 输出:
[
{
path: '/dashboard',
meta: { title: '仪表盘' },
children: [...]
},
{ path: '/dashboard/analysis', meta: { title: '分析页' } },
{ path: '/profile', meta: { title: '个人页' } }
]
*/最佳实践
实例:构建完整的路由管理系统
typescript
import {
formatMenuData,
getFlatMenuList,
getShowMenuList,
getKeepAliveRouterName,
getAllBreadcrumbList
} from '@pt/utils/modules/router';
// 1. 从后端获取原始菜单数据并格式化
const rawMenuData = await fetchMenuFromBackend();
const formattedMenus = formatMenuData(rawMenuData);
// 2. 注册动态路由
const flatMenus = getFlatMenuList(formattedMenus);
flatMenus.forEach(route => {
if (route.component) {
router.addRoute(route);
}
});
// 3. 生成显示菜单
const visibleMenus = getShowMenuList(formattedMenus);
store.commit('setMenuList', visibleMenus);
// 4. 设置需要缓存的路由
const keepAliveNames = getKeepAliveRouterName(formattedMenus);
store.commit('setKeepAliveRoutes', keepAliveNames);
// 5. 预生成所有面包屑并存储
const allBreadcrumbs = getAllBreadcrumbList(formattedMenus);
store.commit('setBreadcrumbs', allBreadcrumbs);
// 6. 全局导航守卫中使用
router.beforeEach((to, from, next) => {
const currentBreadcrumb = store.state.breadcrumbs[to.path] || [];
store.commit('setCurrentBreadcrumb', currentBreadcrumb);
next();
});