react面包屑-动态菜单-权限菜单数据格式化

242 阅读2分钟

使用递归

const menuItems = [
    {
        key: 'sys',
        label: '系统管理',
        children: [
            { key: 'sys/menu', label: '菜单管理' },
            { key: 'sys/role', label: '角色管理' },
            { key: 'sys/user', label: '用户管理' },
        ],
    },
    {
        key: 'shop',
        label: '商城系统',
        children: [
            { key: 'shop/banner', label: 'banner' },
            {
                key: 'shop/category',
                label: '商品分类',
            },
            {
                key: 'shop/goods',
                label: '商品管理',
            },
            {
                key: 'shop/order',
                label: '订单管理',
            },
        ],
    },
    {
        key: 'oa',
        label: 'OA办公系统',

        children: [
            { key: 'oa/list', label: '回复管理' },
            { key: 'oa/lg', label: '日志管理' },
            { key: 'oa/reply', label: '日志回复' },
        ],
    },
]
/**
 * 根据key查找对应label
 * @param {*} list
 * @param {*} key
 */
const findLabelByKey = (list, key) => {
    // 完成方法体实现
    for(let i =0;i<list.length;i++){
        // 判断当前对象的key是否与指定的key相等
         if(list[i].key=key){    
        // 返回匹配到的label属性
            return list[i].label   
        // 判断当前对象是否有children属性(子级)
         }else if(list[i].children){  
        // 递归调用findLabelByKey函数,在子级中继续查找key
           const name = findLabelByKey(list[i].children,key)  
           // 如果在子级中找到了匹配的label属性
           if(name){
               // 返回匹配到的label属性
            return name
           }
         }
    }
    return null; // 如果遍历完整个列表仍未找到匹配的label属性,则返回null或其他标识。
}

//测试
const label = findLabelByKey(menuItems, 'shop/goods')
console.log(label) // 商品管理

实现面包屑

菜单组件

菜单点击事件.jpg

 <Menu
          defaultSelectedKeys={['sys/menu']}
          defaultOpenKeys={['sys']}
          mode="inline"
          theme="dark"
          inlineCollapsed={collapsed}
          items={items}
          onClick={bindPath}   //设置点击事件
        />


 const bindPath = (value) => {
    console.log(value)
     //路由跳转
    navigate(value.key)
     //调用工具函数pathsList()传入value.keyPath  并将返回值存入Lists       
    setLists(pathsList(items, value.keyPath))
  }

创建工具函数

import { AppstoreOutlined } from '@ant-design/icons'

export const items = [
  {
    key: 'sys',
    label: '系统管理',
    icon: <AppstoreOutlined />,
    children: [
      { key: 'sys/menu', label: '菜单管理', icon: <AppstoreOutlined /> },
      { key: 'sys/role', label: '角色管理', icon: <AppstoreOutlined /> },
      { key: 'sys/user', label: '用户管理', icon: <AppstoreOutlined /> },
    ],
  },
  {
    key: 'shop',
    label: '商城系统',
    icon: <AppstoreOutlined />,
    children: [
      { key: 'shop/banner', label: 'banner', icon: <AppstoreOutlined /> },
      { key: 'shop/category', label: '商品分类', icon: <AppstoreOutlined /> },
      { key: 'shop/goods', label: '商品管理', icon: <AppstoreOutlined /> },
      { key: 'shop/order', label: '订单管理', icon: <AppstoreOutlined /> },
    ],
  },
  {
    key: 'oa',
    label: 'OA办公系统',
    icon: <AppstoreOutlined />,
    children: [
      { key: 'oa/list', label: '回复管理', icon: <AppstoreOutlined /> },
      { key: 'oa/lg', label: '日志管理', icon: <AppstoreOutlined /> },
      { key: 'oa/reply', label: '日志回复', icon: <AppstoreOutlined /> },
    ],
  },
]

//通过递归函数的调用知道key返回label
export const pathList = (list, key) => {
  for (let i = 0; i < list.length; i++) {
    if ((list[i].key = key)) {
      return list[i].label
    } else if (list[i].children) {
      const name = pathList(list[i].children, key)
      if (name) {
        return name
      }
    }
  }
  return null
}

/*
*
* setLists(pathsList(items, value.keyPath)) 调用此函数
*
*/
export const pathsList = (list, keyPath) => {
  //创建变量lists
  let lists = []
  //对keyPath进行遍历
   keyPath.forEach(ele => {
    //调用pathList() 得到key对应的label
    const name =  pathList(list,ele)
    lists.push({name,href:ele})
   });
    //结果得到[{name:'商品管理',href:'shop/goods'},{name:'商城系统',href:'shop'}]          在.reverse()反转数组
   return lists.reverse()
}

使用面包屑组件

  const [lists, setLists] = useState()
  <Breadcrumb style={{ margin: '10px' }}>
          <Breadcrumb.Item  key={ele.key}>home</Breadcrumb.Item>
          //?避免lists开始为空报错
          {lists?.map((item) => (
            <Breadcrumb.Item  key={item.href}>{item.name}</Breadcrumb.Item>
          ))}
        </Breadcrumb>

动态菜单

router/index.jsx

import { items} from '@/utils/menu'//引入数据
import React,{lazy} from 'react'  // lazy懒加载
/*
*lazy 函数将要懒加载的组件包裹起来。lazy 函数接受一个函数作为参数,该函数动态地调用 import() 方法来异步*加载组件。
*
*懒加载是一种优化技术,它允许将组件的加载延迟到组件第一次使用时再进行。通过懒加载,可以减少初始加载的 *JavaScript 代码量,从而提高应用程序的性能。
*
*懒加载组件只能在具有动态引入(dynamic import)支持的环境中使用
*/
//创建函数lazyLoad
 const lazyLoad = (path)=>{
   const Com =  lazy(()=>import(`../views/plateform/${path}`))
   return(
    //<React.Suspense> 组件来处理懒加载过程中的加载状态。
    <React.Suspense fallback={<>加载中...</>}>
      <Com></Com>
    </React.Suspense>
   )
  }

  {items.map(ele=>(
            <Route key={ele.key}>
              {ele.children.map(e=>(
              //调用lazyLoad(e.key)
                <Route key={e.key} path={e.key} element={lazyLoad(e.key)}></Route>
              ))}
            </Route>
          ))}

格式化菜单数据

数据格式化.jpg

// 遍历menuList
  menuList.forEach((item) => {
    // childen处理
    let children
    if (item.children && Array.isArray(item.children)) {
      children = formateMenu(item.children)
    }
    // 生成新的菜单对象
    const newItem = children
      ? {
          key: item.path.substring(1),
          label: item.meta.title,
          icon: <AppstoreOutlined />,
          children,
        }
      : {
          key: item.path.substring(1),
          label: item.meta.title,
          icon: <AppstoreOutlined />,
        }

    newMenuList.push(newItem)
  })
  return newMenuList
}