一 实现单个字段的过滤
本方法原文为:JS实现树形结构数据的模糊搜索查询
需求描述:输入 “题2” 字,希望树形结构中带有 “题2” 字的项显示,即使父节点没有,但子节点含有,父节点仍要返回,树节点如下:
let arr = [
{
title: '标题1',
children: [
{
title: '标题11',
children: null
},
{
title: '标题21',
children: null
}
]
},
{
title: '标题2',
children: [
{
title: '标题22',
children: null
}
]
},
{
title: '标题3',
children: null
}
];
代码实现:
let mapTree = (value, arr) => {
let newarr = [];
arr.forEach(element => {
if (element.title.indexOf(value) > -1) { // 判断条件
newarr.push(element);
} else {
if (element.children && element.children.length > 0) {
let redata = mapTree(value, element.children);
if (redata && redata.length > 0) {
let obj = {
...element,
children: redata
};
newarr.push(obj);
}
}
}
});
return newarr;
};
console.log(mapTree('题2', arr));
运行结果:
[
{
title: '标题1',
children: [
{
title: '标题21',
children: null
}
]
},
{
title: '标题2',
children: [
{
title: '标题22',
children: null
}
]
}
]
二 过滤多个属性
本方法同样来源于:JS实现树形结构数据的模糊搜索查询
代码实现如下:
matchTreeData(arr, searchCon) {
let newArr = [];
let searchNameList = ['name', 'code', 'title'];
arr.forEach((item) => {
for (let i = 0, len = searchNameList.length; i < len; i++) {
let nameKey = searchNameList[i];
if (item.hasOwnProperty(nameKey)) {
if (item[nameKey] && item[nameKey].indexOf(searchCon) !== -1) {
newArr.push(item);
break;
} else {
if (item.childList && item.childList.length > 0) {
let resultArr = this.matchTreeData(item.childList, searchCon);
if (resultArr && resultArr.length > 0) {
newArr.push({
...item,
childList: resultArr
})
break;
}
}
}
} else {
continue;
}
}
})
return newArr;
}
三 实现同一属性的多个字段同时过滤,并返回一个父节点
原始数据结构如下:
[
{
id: "1",
name: "一级菜单1",
children: [
{
id: "1-1",
name: "二级菜单1-1",
children: [
{
id: "1-1-1",
name: "三级菜单1-1-1",
},
{
id: "1-1-2",
name: "三级菜单1-1-2",
},
{
id: "1-1-3",
name: "三级菜单1-1-3",
}
]
}
]
}, {
id: "2",
name: "一级菜单2",
children: [
{
id: "2-1",
name: "二级菜单2-1",
}
]
}, {
id: "3",
name: "一级菜单3",
}
]
需要过过滤的字段如下:
const targetMenuName = ["三级菜单1-1-1", "三级菜单1-1-3", "一级菜单3"];
目标结果如下:
[
{
"id": "1",
"name": "一级菜单1",
"children": [
{
"id": "1-1",
"name": "二级菜单1-1",
"children": [
{
"id": "1-1-1",
"name": "三级菜单1-1-1"
},
{
"id": "1-1-3",
"name": "三级菜单1-1-3"
}
]
}
]
},
{
"id": "3",
"name": "一级菜单3"
}
]
实现方法如下:
function filterMenu(menu, targetIds) {
// 递归函数,用于过滤菜单项
function filterRecursive(item, targetIds) {
// 如果当前项的ID匹配目标IDs中的某个ID,保留该项
if (targetIds.includes(item.name)) {
return true;
}
// 如果当前项有子项,递归过滤子项
if (item.children) {
item.children = item.children.filter(child => filterRecursive(child, targetIds));
// 如果子项中有匹配的,保留当前项
if (item.children.length > 0) {
return true;
}
}
// 如果没有匹配的name,且没有子项,删除当前项
return false;
}
// 初始调用
return menu.filter(item => filterRecursive(item, targetIds));
}
四 对tree 中相同父节点的子节点进行合并到同一个父节点中展示。
原始数据如下:
const tree1 = [
{
id: "1",
name: "一级菜单1",
children: [
{
id: "1-1",
name: "二级菜单1-1",
children: [
{
id: "1-1-1",
name: "三级菜单1-1-1"
}
]
}
]
},
{
id: "2",
name: "一级菜单2",
children: [
{
id: "2-1",
name: "二级菜单2-1"
}
]
},
{
id: "3",
name: "一级菜单3"
}
];
const tree2 = [
{
id: "1",
name: "一级菜单1",
children: [
{
id: "1-1",
name: "二级菜单1-1",
children: [
{
id: "1-1-2",
name: "三级菜单1-1-2",
}
]
}
]
},
{
id: "1",
name: "一级菜单1",
children: [
{
id: "1-1",
name: "二级菜单1-1",
children: [
{
id: "1-1-3",
name: "三级菜单1-1-3",
}
]
}
]
},
{
id: "2",
name: "一级菜单2",
children: [
{
id: "2-2",
name: "二级菜单2-2",
}
]
},
];
目标结果如下:
[
{
"id": "1",
"name": "一级菜单1",
"children": [
{
"id": "1-1",
"name": "二级菜单1-1",
"children": [
{
"id": "1-1-1",
"name": "三级菜单1-1-1"
},
{
"id": "1-1-2",
"name": "三级菜单1-1-2"
},
{
"id": "1-1-3",
"name": "三级菜单1-1-3"
}
]
}
]
},
{
"id": "2",
"name": "一级菜单2",
"children": [
{
"id": "2-1",
"name": "二级菜单2-1"
},
{
"id": "2-2",
"name": "二级菜单2-2"
}
]
},
{
"id": "3",
"name": "一级菜单3"
}
]
实现方法如下:
function mergeTree(target, source) {
if (!target?.length && !source?.length) {
if (target?.length) {
return target;
}
if (source?.length) {
return source;
}
return [];
}
const more = [];
source.forEach((sNode) => {
const tNode = target.find((tn) => tn.id === sNode.id);
if (!tNode) {
more.push(sNode);
return;
}
const {children: sChildren, ...props} = sNode;
Object.assign(tNode, props);
mergeTree(tNode.children, sChildren);
});
target.push(...more);
return target;
};