React模态框中实现匹配查询字符串的对象精确路径保留
解决嵌套列表搜索后保留精确路径的问题
你的现有代码仅能筛选出包含匹配项的父节点,但不会修改节点的subItems属性,导致返回的父节点仍携带完整的子列表,而非仅保留到匹配项的路径。要实现预期效果,需要递归处理每个节点时,不仅判断是否保留当前节点,还要替换其subItems为过滤后的子路径。
以下是修改后的实现代码:
type Option = { label: string; value: string; subItems?: Option[]; }; const filterItems = (options: Option[], query: string): Option[] => { const lowerQuery = query.toLowerCase(); return options.reduce((result, option) => { // 判断当前项是否匹配查询 const isCurrentMatch = option.label.toLowerCase().includes(lowerQuery); // 递归过滤子项(如果存在) const filteredSubItems = option.subItems ? filterItems(option.subItems, lowerQuery) : []; // 当前项匹配,或存在匹配的子项时,保留该节点 if (isCurrentMatch || filteredSubItems.length > 0) { result.push({ ...option, // 替换subItems为过滤后的结果(仅当原节点有subItems时) ...(option.subItems && { subItems: filteredSubItems }) }); } return result; }, [] as Option[]); }; const filteredItems = useMemo(() => { return filterItems(options, query); }, [options, query]);
代码逻辑说明
- 统一大小写处理:先将查询字符串转为小写,避免重复转换,提升效率。
- 递归处理子项:对每个节点的
subItems递归调用过滤函数,得到仅包含匹配路径的子列表。 - 节点保留规则:如果当前节点自身匹配查询,或者其过滤后的子列表不为空,则保留该节点。
- 结构重构:保留原节点的
label和value,将subItems替换为过滤后的结果,确保返回的结构仅包含匹配项的完整路径。
测试验证
当查询字符串为Nested baz 2时,函数会逐层递归筛选:
- 顶层仅
Foo节点的子项存在匹配,因此保留Foo; Foo的子项中仅Sub bar 1的子项存在匹配,因此保留Sub bar 1并替换其subItems为仅包含Nested baz 2的数组;- 最终返回的结构与你期望的输出完全一致。
内容的提问来源于stack exchange,提问作者Adam Casey
相关产品推荐
相关产品推荐

