let list = [
{
level: 1,
title: "1"
},
{
level: 4,
title: "1.1",
},
{
level: 2,
title: "1.2",
},
{
level: 3,
title: "1.2.1",
},
{
level: 1,
title: "2",
},
{
level: 2,
title: "2.1",
}
]
let catalogue = [];
let lastTreeNode;
let serial = ["level", "titile", "subNode"];
list.forEach(function(element) {
let currentNode = {
level: element.level,
title: element.title,
subNode: []
}
if (lastTreeNode){
// 如果上一个标题存在,说明已经有构造的树了
if (lastTreeNode.level < currentNode.level){
// 当前标题的级别大于上个标题,所以当前标题是上个标题的子标题
currentNode.parentNode = lastTreeNode;
lastTreeNode.subNode.push(currentNode);
}else if (lastTreeNode.level == currentNode.level){
// 当前标题的级别等于上个标题,说明两个标题同级别,且在一个父节点下,这里要分两种情况
if (lastTreeNode.parentNode){
currentNode.parentNode = lastTreeNode.parentNode;
lastTreeNode.parentNode.subNode.push(currentNode);
}else{
catalogue.push(currentNode);
}
}else if (lastTreeNode.level > currentNode.level){
/*
旧思路
// 当前标题的级别小于上个标题,则要算出其级别差
let fix = lastTreeNode.level - currentNode.level;
// 通过级别差找到当前标题的同级标题
let tempNode = lastTreeNode;
for (let i = 0; i < fix; i++){
if(!tempNode.parentNode){
break;
}
if (tempNode.level == currentNode.level){
break;
}
tempNode = tempNode.parentNode;
}
if (tempNode.parentNode){
currentNode.parentNode = tempNode;
tempNode.parentNode.subNode.push(currentNode);
}else{
catalogue.push(currentNode);
}
*/
// 这里会出现一个问题:
/*
比如:
h1
h3
H4
h2
跨级别的标题,应当找到上级标题的最趋近(大)于当前标题的父节点
比如当前标题为h2,则要找到h4的上级,如果h4的上级还是大于h2,则还得继续向上找
否则会导致找到一个h3作为h2的上级
特殊情况:
向上找直接找到了一个空,说明h2会作为一个根节点存在
*/
let tempParentNode = lastTreeNode;
while(true){
if (!tempParentNode){
break;
}
if (tempParentNode.level < currentNode.level){
//找到直接父级就跳出
break;
}
tempParentNode = tempParentNode.parentNode;
}
if (tempParentNode){
currentNode.parentNode = tempParentNode;
tempParentNode.subNode.push(currentNode);
}else{
catalogue.push(currentNode);
}
}
}else{
catalogue.push(currentNode);
}
lastTreeNode = currentNode;
});
console.log(JSON.stringify(catalogue, serial))
console