我们经常需要整理后端返回的数据,比如前端展示的树结构很可能就要把后端返回的 Json 整理成嵌套的层级结构。
现在的需求就是把后端返回的数据形式的 json 按照 parent_id 和 id 整理成层级包含的树结构。
最开始由于一些错误的思想被引入了弯路:先循环取出第一层的数据,再循环取出第一层数据的子数据赋给第一层。这样的问题就是这能处理两层的,不够通用。
现在新的想法是先把数据遍历一遍,看看哪些 item 有 children,然后重新循环数据,为有 children 的那些 item 找出它们所有的 child 并赋给它们。
下面我们开始吧:
- 遍历数据,看看哪些 item 有 children
for (let i = 0; i < data.length; i++) {
data[i].hasChildPermission = false;
data[i].children = []; // 顺便为所有的 item 添加 children 字段,后面直接 push
if (data.find(item => {
return item.parent_id - data[i].id === 0;
})) {
data[i].hasChildPermission = true;
}
}
- 为有 children 的那些 item 找出它们所有的 child 并赋给它们
注意这里是从后往前,因为不止有一级,这样可以让某一节点的子节点找全了自己全部的子节点之后再赋给这个节点。可能语言不那么好解释清楚,从前往后试试结果就很明了了。
for (let i = data.length - 1; i >= 0; i--) {
if (data[i].hasChildPermission) {
for (let j = 0; j < data.length; j++) {
if (data[i].id - data[j].parent_id === 0) {
data[i].children.push(data[j]);
data[j].needRemove = true;
}
}
}
}
- 把已经赋给父节点的需要去掉的子节点从数组中去掉。
这里也走了一点弯路,刚开始是在上一步直接 slice 去掉那一项,这样出来的结果怎么也不对,因为我们在循环这个数组,但是这个数组本身又在变动,所以结果肯定不对。
let newData = [];
newData = JSON.parse(JSON.stringify(data));
_.remove(newData, item => {
return item.needRemove;
});