如何在Material UI RichTreeView中实现按Label过滤树形节点
Material UI RichTreeView 树形节点过滤实现方案
核心逻辑
不需要扁平化数据,直接通过递归遍历树形结构实现过滤:保留匹配关键词的节点,同时如果父节点包含匹配的子节点,也保留父节点(确保子节点能正常显示)。
实现步骤
1. 编写递归过滤函数
这个函数会遍历树形数组,返回符合条件的节点结构:
const filterTree = (items, searchTerm) => { // 空搜索词直接返回原数据 if (!searchTerm.trim()) return items; const lowercasedTerm = searchTerm.toLowerCase(); return items.reduce((filtered, item) => { // 检查当前节点标签是否匹配(忽略大小写) const nodeMatches = item.label.toLowerCase().includes(lowercasedTerm); // 递归过滤子节点 const filteredChildren = filterTree(item.children || [], searchTerm); // 当前节点匹配,或者有匹配的子节点,就保留该节点 if (nodeMatches || filteredChildren.length > 0) { filtered.push({ ...item, children: filteredChildren // 替换为过滤后的子节点列表 }); } return filtered; }, []); };
2. 适配现有组件
在你的组件中,实时根据搜索输入生成过滤后的数组,传给RichTreeView的items属性:
import React, { useState, useMemo } from 'react'; import { RichTreeView, TreeItem } from '@mui/x-tree-view/RichTreeView'; import { TextField } from '@mui/material'; // 这里放入上面的filterTree函数 const TreeViewWithSearch = () => { const [searchTerm, setSearchTerm] = useState(''); // 你的原始树形数据 const originalTreeData = [ // 示例数据,替换成你自己的数组 { id: 'root', label: 'Root', children: [{ id: 'child1', label: 'Child Node 1' }, { id: 'child2', label: 'Child Node 2' }] } ]; // 使用useMemo缓存过滤结果,避免重复计算 const filteredTreeData = useMemo(() => { return filterTree(originalTreeData, searchTerm); }, [originalTreeData, searchTerm]); return ( <div style={{ width: 300, margin: '20px' }}> {/* 搜索输入框 */} <TextField label="搜索节点" value={searchTerm} onChange={(e) => setSearchTerm(e.target.value)} fullWidth margin="normal" /> {/* 过滤后的树形视图 */} <RichTreeView items={filteredTreeData} renderItem={({ item, label, icon, expandIcon }) => ( <TreeItem itemId={item.id} label={label} icon={icon} expandIcon={expandIcon} /> )} /> </div> ); }; export default TreeViewWithSearch;
优化与调整
- 匹配规则自定义:如果需要精确匹配、开头匹配等,修改
nodeMatches的判断逻辑即可,比如item.label.toLowerCase().startsWith(lowercasedTerm)。 - 节点结构适配:如果你的节点子节点不是
children字段,替换函数中item.children为你实际的字段名。 - 大数据量优化:如果树形数据量很大,
useMemo可以有效减少重复过滤的性能开销。
内容的提问来源于stack exchange,提问作者Bouchet
相关产品推荐
相关产品推荐

