感觉每天都带着口罩上班好奇怪
哈哈!!
他们带我也带
在后端返回的数据式中,以以下格式存储信息是相当普遍的,尤其是在存在一对多父/子节点关系的情况下:
const data = [
{ id: 56, parentId: 62 },
{ id: 81, parentId: 80 },
{ id: 74, parentId: null },
{ id: 76, parentId: 80 },
{ id: 63, parentId: 62 },
{ id: 80, parentId: 86 },
{ id: 87, parentId: 86 },
{ id: 62, parentId: 74 },
{ id: 86, parentId: 74 },
];
那么,如何从这种对象数组格式转变为分层树格式?
{
id: 74,
parentId: null,
children: [
{
id: 62,
parentId: 74,
children: [{ id: 56, parentId: 62 }, { id: 63, parentId: 62 }],
},
{
id: 86,
parentId: 74,
children: [
{
id: 80,
parentId: 86,
children: [{ id: 81, parentId: 80 }, { id: 76, parentId: 80 }],
},
{ id: 87, parentId: 86 },
],
},
],
};
数组中的每个元素都是一个“节点”。一个节点可以是多个节点的“父级”,也可以是一个节点的“子级”。在下面的图片,86是80和87的“父”。74的“孩子” 是86。我们树的顶部节点是“根”。
要构建我们的树,我们将要:
遍历data数组
查找当前元素的父元素
在父元素的对象中,添加对子元素的引用
如果某个元素没有父元素,那么我们知道这将是树的“根”元素
首先保存对应关系,方便我们通过儿子可以快速找到父亲。
const idMapping = data.reduce((acc, el, i) => {
acc[el.id] = i;
return acc;
}, {});
通过对象是引用类型的机制我们可以这样创建树结构。
let root;
data.forEach(el => {
// 根节点
if (el.parentId === null) {
root = el;
return;
}
// 父节点
const parentEl = data[idMapping[el.parentId]];
// 子节点
parentEl.children = [...(parentEl.children || []), el];
});
当您利用JavaScript对象引用时,这实际上变得相当容易。无需递归即可在O(n)时间内完成。