前端基础(三十七):属性结构数据进行关键字筛选

效果

核心源码

ts 复制代码
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;
    });
}

源码

ts 复制代码
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;
相关推荐
小兵张健1 小时前
价值1000的 AI 工作流:Codex 通用前端协作模式
前端·aigc·ai编程
sunny_1 小时前
面试踩大坑!同一段 Node.js 代码,CJS 和 ESM 的执行顺序居然是反的?!99% 的人都答错了
前端·面试·node.js
拉不动的猪1 小时前
移动端调试工具VConsole初始化时的加载阻塞问题
前端·javascript·微信小程序
ayqy贾杰3 小时前
Agent First Engineering
前端·vue.js·面试
IT_陈寒3 小时前
SpringBoot实战:5个让你的API性能翻倍的隐藏技巧
前端·人工智能·后端
iceiceiceice4 小时前
iOS PDF阅读器段评实现:如何从 PDFSelection 精准还原一个自然段
前端·人工智能·ios
大金乄4 小时前
封装一个vue2的elementUI 表格组件(包含表格编辑以及多级表头)
前端·javascript
葡萄城技术团队5 小时前
【性能优化篇】面对万行数据也不卡顿?揭秘协同服务器的“片段机制 (Fragments)”
前端
程序员阿峰5 小时前
2026前端必备:TensorFlow.js,浏览器里的AI引擎,不写Python也能玩转智能
前端
Jans5 小时前
Shipfe — Rust 写的前端静态部署工具:一条命令上线 + 零停机 + 可回滚 + 自动清理
前端