前言
作为苦逼的前端攻城狮,如果后端不愿意对数据进行处理,那么我们只能自给自足了~🚀
小编上周遇到了个需求:数据以树状的形式展开,且支持查询。
这个需求听起来很简单,但上手处理数据就发现了🙁对小编来讲,有点难度。
由于后端小伙不愿意返回符合查询条件的树状数据,那么这个重任只能交给无助的小编了~
🚀🚀🚀特此文章记录一下🚀🚀🚀
思路梳理
1.后端返回的是树状数据,所以我们首先需要将数据扁平化;
// 数据扁平化
const dealTreeData = (data: any) => {
let arrTree: any = []
data.forEach((ele: any) => {
let obj = { ...ele }
delete obj.children
arrTree.push(obj)
if (ele?.children?.length) {
arrTree.push(...dealTreeData(ele.children))
}
});
return arrTree;
}
2.筛选出符合条件的数据;
let dealData = dealTreeData(treeData)
let arr = dealData.filter((ele: any) => ele.isFilter)
3.根据筛选出来的数据,寻找数据所有父级;
let res: any = [...arr] || []
arr.forEach((x: any) => {
let arrtemp = treeFindDataByFactor(treeData, (d: any) => d.label.indexOf(x.label) !== -1)
arrtemp.forEach((y: any) => {
res.push(y)
})
})
4.去重;
const result = Array.from(new Set(res.map(JSON.stringify)), JSON.parse);
5.将扁平数据转换成树状数据;
// 扁平数据转tree
const changeTreeData = (arr: any, parentId: number) => {
function loop(parentId: number) {
return arr.reduce((pre: any, cur: any) => {
if (cur.pid === parentId) {
cur.children = loop(cur.id)
pre.push(cur)
}
return pre
}, [])
}
return loop(parentId)
}
上硬菜(完整代码)
const treeData: any = [
{
id: 1,
pid: 0,
label: 'Item2',
isFilter: true,
children: [{
id: 9,
pid: 1,
label: 'Item2-1',
isFilter: false,
children: []
}, {
id: 10,
pid: 1,
label: 'Item2-2',
isFilter: false,
children: [{
id: 11,
pid: 10,
label: 'Item2-2-1',
isFilter: false,
children: [{
id: 13,
pid: 11,
label: 'Item2-2-1-1',
isFilter: false,
children: []
}]
}, {
id: 12,
pid: 10,
label: 'Item',
isFilter: false,
children: [{
id: 14,
pid: 12,
label: 'Item2-2-2-1',
isFilter: false,
children: [{
id: 15,
pid: 14,
label: 'Item2-2-2-1-1',
isFilter: false,
children: [{
id: 16,
pid: 15,
label: 'Item2-2-2-1-1-1',
isFilter: false,
children: []
}, {
id: 17,
pid: 15,
label: 'Item2-2-2-1-1-2',
isFilter: false,
children: []
}, {
id: 18,
pid: 15,
label: 'Item2-2-2-1-1-3',
isFilter: true,
children: []
}]
},]
}]
}]
}]
}, {
id: 2,
pid: 0,
label: 'Item3',
isFilter: false,
children: [{
id: 19,
pid: 2,
label: 'Item3-1',
isFilter: false,
children: [{
id: 22,
pid: 19,
label: 'Item3-1-1',
isFilter: false,
children: []
}, {
id: 23,
pid: 19,
label: 'Item3-1-2',
isFilter: false,
children: [{
id: 28,
pid: 23,
label: 'Item3-1-2-1',
isFilter: false,
children: [{
id: 29,
pid: 28,
label: 'Item3-1-2-1-1',
isFilter: false,
children: []
}, {
id: 30,
pid: 28,
label: 'Item3-1-2-1-2',
isFilter: false,
children: [{
id: 32,
pid: 30,
label: 'Item3-1-2-1-3',
isFilter: false,
children: []
},]
}, {
id: 31,
pid: 28,
label: 'Item3-1-2-1',
isFilter: true,
children: []
},]
},]
},]
}, {
id: 20,
pid: 2,
label: 'Item3-2',
isFilter: false,
children: [{
id: 24,
pid: 20,
label: 'Item3-2-1',
isFilter: false,
children: []
},]
}, {
id: 21,
pid: 2,
label: 'Item3-3',
isFilter: false,
children: [{
id: 25,
pid: 21,
label: 'Item3-3-1',
isFilter: false,
children: [{
id: 26,
pid: 25,
label: 'Item3-3-1-1',
isFilter: false,
children: []
}, {
id: 27,
pid: 25,
label: 'Item3-3-1-2',
isFilter: false,
children: []
},]
},]
},]
},
]
// 数据扁平化
const dealTreeData = (data: any) => {
let arrTree: any = []
data.forEach((ele: any) => {
let obj = { ...ele }
delete obj.children
arrTree.push(obj)
if (ele?.children?.length) {
arrTree.push(...dealTreeData(ele.children))
}
});
return arrTree;
}
// 扁平数据转tree
const changeTreeData = (arr: any, parentId: number) => {
function loop(parentId: number) {
return arr.reduce((pre: any, cur: any) => {
if (cur.pid === parentId) {
cur.children = loop(cur.id)
pre.push(cur)
}
return pre
}, [])
}
return loop(parentId)
}
/**
* 根据条件查询出树级结构的对应数据
* @param tree 树结构数据
* @param func 条件函数
* @param findArr 找到的数据
* @returns {{length}|[]|*|[]|*[]}
*/
const treeFindDataByFactor = (tree: any, func: any, findArr: any = []): [] => {
if (!tree || !tree.length) {
return [];
}
for (const data of tree) {
let tempData = { ...data }
delete tempData.children
findArr.push(tempData);
if (func(data)) {
return findArr;
}
if (data.children && data.children.length) {
const findChildren = treeFindDataByFactor(data.children, func, findArr);
if (findChildren.length) return findChildren;
}
findArr.pop();
}
return [];
}
const filterData = (tree: any) => {
let dealData = dealTreeData(tree)
let arr = dealData.filter((ele: any) => ele.isFilter)
let res: any = [...arr]||[]
console.log('符合条件的数据:',arr)
arr.forEach((x: any) => {
let arrtemp = treeFindDataByFactor(treeData, (d: any) => d.label.indexOf(x.label) !== -1)
arrtemp.forEach((y: any) => {
res.push(y)
})
})
const result = Array.from(new Set(res.map(JSON.stringify)), JSON.parse);
console.log('去重后的数据:',result)
return changeTreeData(result, 0)
}
let treeResult=filterData(treeData)
console.log('初始数据:',treeData);
console.log('筛选条件:isFilter为true');
console.log('筛选数据:',treeResult);