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<IMenu>; path: string; icon?: string; } const MenuComps: React.FC = () => { const [menuData, setMenuData] = useState<Array<IMenu>>([]) 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 <Menu.Item key={item.title}>{ item.title }</Menu.Item> } // 渲染含有children的目录 const renderChildMenu = (item: IMenu) => { return <SubMenu key={item.title} title={item.title}> { item.children.map((child) => { return renderMenu(child) }) } </SubMenu> } // 渲染菜单 const renderMenu = (item: IMenu) => { return item.children.length ? renderChildMenu(item) : renderNoChildMenu(item) } return ( <MenuWrapper className="menu-wrapper"> <div className="menu-header"> <img src={logoIcon} alt="" /> <span>React Demo</span> </div> <Menu onClick={handleClick} style={{ width: '100%', marginTop: '2px' }} defaultSelectedKeys={['1']} defaultOpenKeys={[]} mode="inline" > {/* <SubMenu key="sub1" title="Navigation One"> <Menu.ItemGroup key="g1" title="Item 1"> <Menu.Item key="1">Option 1</Menu.Item> <Menu.Item key="2">Option 2</Menu.Item> </Menu.ItemGroup> <Menu.ItemGroup key="g2" title="Item 2"> <Menu.Item key="3">Option 3</Menu.Item> <Menu.Item key="4">Option 4</Menu.Item> </Menu.ItemGroup> </SubMenu> <Menu.Item key="12">Option 12</Menu.Item> */} { menuData.map((item: any) => renderMenu(item)) } </Menu> </MenuWrapper> ) } export default MenuComps
展示效果