In the daily development of the front end, we are actually relatively easy to deal with the tree structure. For example, we need to generate a tree menu on the page from the menu list returned by the back end. It could also be option data that converts list data into tree selectors. You might be looking for some data in the tree and so on.
So I’m going to share with you the approach I used in my projects.
1. Transform the list into a tree structure
1.1 My Thinking
This approach assumes that all the parent nodes appear before the child nodes. First, iterate through the list and put each item into a map. At the same time, determine whether the parent node of each item is in the Map object. If so, put this item under the children attribute of the parent node. So the end of the loop can generate the tree of data.
1.2 Code Implementation
const createTree = function (list=[]) {
let tree = [];
let map = {};
list.forEach(item= > {
const newItem = {
id: item.id,
pid: item.pid,
name: item.name,
code: item.code,
children: [],}; map[item.id] = newItem;// Check whether it is the root node
if (item.pid === -1) {
tree.push(newItem);
} else{ map[newItem.pid].children.push(newItem); }});return tree;
};
const list = [
{
id: 1.pid: -1.name: "Zhang SAN 1 '.code: '1'
},
{
id: 11.pid: 1.name: 'Joe 11'.code: '11'
},
{
id: 12.pid: 1.name: 'Joe 12'.code: '12'
},
{
id: 13.pid: 1.name: 'Joe 13'.code: '13'
},
{
id: 2.pid: -1.name: 'Joe 2'.code: '2'
},
{
id: 21.pid: 2.name: 'Joe 2'.code: '21'
},
{
id: 211.pid: 21.name: 'Joe 211'.code: '211'},]console.log(createTree(list));
Copy the code
1.3 Upgrade and Renovation
There is a condition in our method that the parent node must appear before the child node, otherwise there will be a problem. So how do you handle the parent node appearing after the child node?
We can add a map to store children whose parents have not yet appeared, and then loop through to determine if the staging area has children, and if so, add them to the children property of the staging area.
The following code
const createTree = function (list=[]) {
const tree = [];
const map = {};
const waitPushObj = {};
list.forEach(item= > {
const newItem = {
id: item.id,
pid: item.pid,
name: item.name,
code: item.code,
children: [],}; map[item.id] = newItem;// Check whether it is the root node
if (item.pid === -1) {
tree.push(newItem);
} else if (map[item.pid]) {
map[item.pid].children.push(newItem);
} else {
if(! waitPushObj[item.pid]) { waitPushObj[item.pid] = []; } waitPushObj[item.pid].push(newItem); }// Determine whether the staging area has its own child nodes
if (waitPushObj[item.id]) {
newItem.children = waitPushObj[item.id];
delete waitPushObj[item.id];
}
// You can omit this judgment
if (!map[item.id]) {
map[item.id] = newItem;
}
});
return tree;
};
const list = [
{
id: 11.pid: 1.name: 'Joe 11'.code: '11'
},
{
id: 12.pid: 1.name: 'Joe 12'.code: '12'
},
{
id: 13.pid: 1.name: 'Joe 13'.code: '13'
},
{
id: 21.pid: 2.name: 'Joe 2'.code: '21'
},
{
id: 1.pid: -1.name: "Zhang SAN 1 '.code: '1'
},
{
id: 211.pid: 21.name: 'Joe 211'.code: '211'
},
{
id: 2.pid: -1.name: 'Joe 2'.code: '2'},]console.log(createTree(list));
Copy the code
2. Find an element
2.1 Search by iteration
const tree = [
{
"id": 1."pid": -1."name": "Zhang SAN 1"."code": "1"."children": [{"id": 11."pid": 1."name": "Zhang SAN 11"."code": "11"."children": []}, {"id": 12."pid": 1."name": "Zhang SAN's 12"."code": "12"."children": []}, {"id": 13."pid": 1."name": "Zhang SAN 13"."code": "13"."children": []}]}, {"id": 2."pid": -1."name": "Zhang SAN 2"."code": "2"."children": [{"id": 21."pid": 2."name": "Zhang SAN 2"."code": "21"."children": [{"id": 211."pid": 21."name": "Zhang SAN's 211"."code": "211"."children": []}]}]const findNode = function (tree, id) {
const list = [...tree];
let p = list.shift();
while (p) {
if (p.id === id) return p;
if(p.children) { list.push(... p.children) } p = list.shift(); }return null;
}
console.log(findNode(tree, 211))
Copy the code