Nested Tree vs Flat Tree
The tree component is very common and useful. Have you ever noticed that not all the tree components are nested?
Background
Our mission is to visualize a tree data structure in the browser.
// A basic tree data structure
const treeData = {
id: 0,
name: "root",
children: [
{
id: 1,
name: "node 1",
children: [
{
id: 3,
name: "node 1.1"
}
]
},
{
id: 2,
name: "node 2",
children: [
{
id: 4,
name: "node 2.1"
}
]
}
]
};
It has two children and each child has a child.
Nested Tree
I naturally assumed that the structure of the tree component is nested. This is the most intuitive way to generate a tree structure. Just traversal the data structure and convert it to an HTML element.
function nestedTreeGenerator(treeData, depth) {
const nodes = [];
for (const node of treeData) {
const $node = $("<div>");
$node.addClass("tree-node");
$node.attr("data-depth", depth);
$node.append(`<div class="tree-node-name">${node.name}</div>`);
if (Array.isArray(node.children) && node.children.length != 0) {
$node.append(nestedTreeGenerator(node.children, depth + 1));
}
nodes.push($node);
}
return nodes;
}
It will generate HTML as below. It is a typical HTML structure and we can easily add a collapse/expand feature to the tree later.
<div class="tree-node" data-depth="0">
<div class="tree-node-name">root</div>
<div class="tree-node" data-depth="1">
<div class="tree-node-name">node 1</div>
<div class="tree-node" data-depth="2">
<div class="tree-node-name">node 1.1</div>
</div>
</div>
<div class="tree-node" data-depth="1">
<div class="tree-node-name">node 2</div>
<div class="tree-node" data-depth="2">
<div class="tree-node-name">node 2.1</div>
</div>
</div>
</div>
Flat Tree
The flat tree is a list but looks like a tree.
function flatTreeGenerator(treeData, depth, parentId) {
let nodes = [];
for (const node of treeData) {
const $node = $("<div>");
$node.addClass("tree-node");
$node.attr("data-depth", depth);
$node.attr("data-node-id", node.name.split(" ")[1]);
$node.append(`<div class="tree-node-name">${node.name}</div>`);
$node.css("padding-left", `${depth}rem`);
if (parentId != null) {
// Record the parent id
// Use it when you need to collapse/expand children of a node
$node.attr("data-parent-id", parentId);
}
nodes.push($node);
if (Array.isArray(node.children) && node.children.length != 0) {
// flat all nodes on the same level
nodes = [
...nodes,
...flatTreeGenerator(node.children, depth + 1, node.id)
];
}
}
return nodes;
}
The final result is the same as below. I saved the node-id
and parent-id
so we didn't lose the hierarchy information. The indentation is not naturally formed so you need to do it by yourself.
<div class="tree-node" data-depth="0" style="padding-left: 0rem;">
<div class="tree-node-name">root</div>
</div>
<div class="tree-node" data-depth="1" data-node-id="1" data-parent-id="0" style="padding-left: 1rem;">
<div class="tree-node-name">node 1</div>
</div>
<div class="tree-node" data-depth="2" data-node-id="1.1" data-parent-id="1" style="padding-left: 2rem;">
<div class="tree-node-name">node 1.1</div>
</div>
<div class="tree-node" data-depth="1" data-node-id="2" data-parent-id="0" style="padding-left: 1rem;">
<div class="tree-node-name">node 2</div>
</div>
<div class="tree-node" data-depth="2" data-node-id="2.1" data-parent-id="2" style="padding-left: 2rem;">
<div class="tree-node-name">node 2.1</div>
</div>
Full Example
These two trees look like same. But hover your mouse on the tree node you will find the behavior is a little different. The nested tree's background color always has an indent but the flat tree doesn't.
Summary
I first learned about the flat tree after I downloaded VS Code. I found VS Code gracefully displays my folder structure, it looks like a list but you can collapse/expand folders. The most thing I like is the whole column will highlighted when you hover your cursor on a folder or file.
With the nested tree, you can easily implement tree-related features on it based on its hierarchical structure.
The flat tree looks more concise. Thanks to its simple structure, it is easy to apply CSS style for it.
Well, they both have pros and cons, choose what you need based on your requirements.
Source: View source