我們經(jīng)常需要整理后端返回的數(shù)據(jù),比如前端展示的樹結(jié)構很可能就要把后端返回的 Json 整理成嵌套的層級結(jié)構。
現(xiàn)在的需求就是把后端返回的數(shù)據(jù)形式的 json 按照 parent_id 和 id 整理成層級包含的樹結(jié)構。
最開始由于一些錯誤的思想被引入了彎路:先循環(huán)取出第一層的數(shù)據(jù),再循環(huán)取出第一層數(shù)據(jù)的子數(shù)據(jù)賦給第一層。這樣的問題就是這能處理兩層的,不夠通用。
現(xiàn)在新的想法是先把數(shù)據(jù)遍歷一遍,看看哪些 item 有 children,然后重新循環(huán)數(shù)據(jù),為有 children 的那些 item 找出它們所有的 child 并賦給它們。
下面我們開始吧:
- 遍歷數(shù)據(jù),看看哪些 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 并賦給它們
注意這里是從后往前,因為不止有一級,這樣可以讓某一節(jié)點的子節(jié)點找全了自己全部的子節(jié)點之后再賦給這個節(jié)點。可能語言不那么好解釋清楚,從前往后試試結(jié)果就很明了了。
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;
}
}
}
}
- 把已經(jīng)賦給父節(jié)點的需要去掉的子節(jié)點從數(shù)組中去掉。
這里也走了一點彎路,剛開始是在上一步直接 slice 去掉那一項,這樣出來的結(jié)果怎么也不對,因為我們在循環(huán)這個數(shù)組,但是這個數(shù)組本身又在變動,所以結(jié)果肯定不對。
let newData = [];
newData = JSON.parse(JSON.stringify(data));
_.remove(newData, item => {
return item.needRemove;
});