React + antd (Menu组件渲染多级菜单)


菜单数据结构

[
  {
    "title": "首页",
    "icon": null,
    "path": "/home",
    "children": []
  },
  {
    "title": "Option",
    "icon": null,
    "path": "/home",
    "children": [
      {
        "title": "Option 1",
        "icon": null,
        "path": "/home",
        "children": []
      },
      {
        "title": "Option 2",
        "icon": null,
        "path": "/home",
        "children": [
          {
            "title": "Option 3",
            "icon": null,
            "path": "/home",
            "children": []
          }
        ]
      }
    ]
  }
]

实现代码

import React, { useState, useEffect } from "react";
import { Menu } from 'antd';
import { MenuWrapper } from './styled'
import logoIcon from '@/assets/img/logo.svg'
import { getMenuList } from '@/api/menu'

const { SubMenu } = Menu;

interface IMenu {
  title: string;
  children: Array;
  path: string;
  icon?: string;
}

const MenuComps: React.FC = () => {
  const [menuData, setMenuData] = useState>([]) 
  const handleClick = (e: any) => {
    console.log('click ', e);
  }
  // 获取菜单数据
  const getMenuData = async () => {
    const res = await getMenuList()
    setMenuData(res.data)
  }
  useEffect(() => {
    getMenuData()
  }, [])

  // 渲染不含children的目录
  const renderNoChildMenu = (item: IMenu) => {
    return { item.title }
  }
  // 渲染含有children的目录
  const renderChildMenu = (item: IMenu) => {
    return 
      { 
        item.children.map((child) => {
          return renderMenu(child)
        })
      }
    
  }
  // 渲染菜单
  const renderMenu = (item: IMenu) => {
    return item.children.length ? renderChildMenu(item) : renderNoChildMenu(item)
  }
  return (
    "menu-wrapper">
      
"menu-header"> <span"" /> React Demo
<Menu onClick={handleClick} style={{ width: '100%', marginTop: '2px' }} defaultSelectedKeys={['1']} defaultOpenKeys={[]} mode="inline" > {/* Option 1 Option 2 Option 3 Option 4 Option 12 */} { menuData.map((item: any) => renderMenu(item)) }
) } export default MenuComps

展示效果