Skip to content

路由工具

概述

本文档介绍了一组用于处理路由和菜单数据的实用工具函数。这些函数主要用于处理嵌套菜单结构,实现常见的路由操作,如过滤当前路由、扁平化处理、获取面包屑导航等功能。

数据结构定义

这些函数基于以下菜单数据结构:

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();
});

Released under the MIT License.