效果
核心源码
type MenuItem = { label: string ; key: string | number ; icon? : React. ReactNode; children? : MenuItem[ ] ; type? : 'group' ;
} function filterTreeData ( tree: MenuItem[ ] , keyword: string ) : MenuItem[ ] { return tree. filter ( ( node: MenuItem) => { if ( node. label. includes ( keyword) ) { return true ; } if ( Array . isArray ( node. children) ) { node. children = filterTreeData ( node. children, keyword) ; return ! ! node. children?. length; } return false ; } ) ;
}
源码
import React, { useState} from 'react' ;
import { BarChartOutlined, CompassOutlined, DatabaseOutlined, DeploymentUnitOutlined, DesktopOutlined, SettingOutlined, FundProjectionScreenOutlined, FundViewOutlined, HomeOutlined, MenuFoldOutlined, MenuUnfoldOutlined, MessageOutlined, TrophyOutlined, VerifiedOutlined,
} from '@ant-design/icons' ;
import { Flex, Button, Menu as AntdMenu} from 'antd' ;
import Search from "antd/es/input/Search" ;
import { SearchProps} from "antd/lib/input" ; type MenuItem = { label: string ; key: string | number ; icon? : React. ReactNode; children? : MenuItem[ ] ; type? : 'group' ;
} function getItem ( label: React. ReactNode, key: React. Key, icon? : React. ReactNode, children? : MenuItem[ ] , type? : 'group' , ) : MenuItem { return { key, icon, children, label, type, } as MenuItem;
} function filterTreeData ( tree: MenuItem[ ] , keyword: string ) : MenuItem[ ] { return tree. filter ( ( node: MenuItem) => { if ( node. label. includes ( keyword) ) { return true ; } if ( Array . isArray ( node. children) ) { node. children = filterTreeData ( node. children, keyword) ; return ! ! node. children?. length; } return false ; } ) ;
} const Menu: React. FC = ( ) => { const menuItems: MenuItem[ ] = [ getItem ( '首页' , '1' , < HomeOutlined/ > ) , getItem ( '平台管理' , '2' , < DesktopOutlined/ > , [ getItem ( '学生管理' , '2-1' ) , getItem ( '教师管理' , '2-2' ) , getItem ( '班级管理' , '2-3' ) , getItem ( '任务管理' , '2-4' , null , [ getItem ( '课程管理' , '2-4-1' ) , getItem ( '发布任务' , '2-4-2' ) , ] ) , getItem ( '作业管理' , '2-5' ) , getItem ( '答卷管理' , '2-6' , null , [ getItem ( '批卷列表' , '2-6-1' ) , getItem ( '批卷结果' , '2-6-2' ) , ] ) , ] ) , getItem ( '平台资源' , '3' , < DatabaseOutlined/ > ) , getItem ( '教学实训' , '4' , < MessageOutlined/ > ) , getItem ( '培训认证' , '5' , < VerifiedOutlined/ > ) , getItem ( '技能竞赛' , '6' , < TrophyOutlined/ > ) , getItem ( '科研实验' , '7' , < DeploymentUnitOutlined/ > ) , getItem ( '数据平台' , '8' , < BarChartOutlined/ > ) , getItem ( '算法平台' , '9' , < FundProjectionScreenOutlined/ > ) , getItem ( '系統管理' , '10' , < CompassOutlined/ > ) , getItem ( '系统监控' , '11' , < FundViewOutlined/ > ) , getItem ( '系統工具' , '12' , < SettingOutlined/ > ) , ] ; const [ items, setItems] = useState < MenuItem[ ] > ( menuItems) ; const [ collapsed, setCollapsed] = useState ( false ) ; const toggleCollapsed = ( ) => { setCollapsed ( ! collapsed) ; } ; const onSearch: SearchProps[ 'onSearch' ] = ( value, _e, _info) => { setItems ( filterTreeData ( menuItems, value) ) ; } ; return ( < > < div className= "menu-tool" > < Flex gap= { 10 } > { collapsed ? '' : ( < Search placeholder= "在此输入关键词..." onSearch= { onSearch} / > ) } < Button block= { collapsed} type= "primary" onClick= { toggleCollapsed} icon= { collapsed ? < MenuUnfoldOutlined/ > : < MenuFoldOutlined/ > } / > < / Flex> < / div> < AntdMenu defaultSelectedKeys= { [ '1' ] } mode= "inline" inlineCollapsed= { collapsed} items= { items} / > < / > ) ;
} ; export default Menu;