树状结构列表,这个技术点之前有写过了,是基于vue讲解,但似乎都没有解决痛点,最基础的原生JS该怎么实现呢?
这篇文章会全面详细的介绍树状结构列表的实现,从数据处理成树状结构,到动态生成dom节点渲染页面。
确定原始数据结构
原始数据是需要按照下面这种结构来定义的,如果原始数据已经是被后端处理成树状结构,就可以省略这一步骤。
let data = [ { "id": "1", "name": "1", "fatherId": "0", }, { "id": "2", "name": "1-1", "fatherId": "1" }, { "id": "3", "name": "1-2", "fatherId": "1" }, { "id": "4", "name": "1-1-1", "fatherId": "2" }, { "id": "5", "name": "1-1-2", "fatherId": "2" }, { "id": "6", "name": "2", "fatherId": "0" }, { "id": "7", "name": "1-2-1", "fatherId": "3" }];
使用map处理数据
const map = {};const val = [];data.forEach((item) => { map[item.id] = item;});data.forEach((item) => { const parent = map[item.fatherId]; if (parent) { (parent.children || (parent.children = [])).push(item); } else { val.push(item); }});
把数组val打印出来看一下。
html结构
<div id="d0" class="treeItem"></div>
动态创建dom
将动态创建dom封装成一个方法,里面使用了递归。循环val数组调用这个方法,即可以实现动态创建dom。
const tree = document.getElementById("tree");function createLi(data) { const fid = `d${data.fatherId}`; const div = document.getElementById(fid); const treeItem = document.createElement("div"); treeItem.id = `d${data.id}`; treeItem.className = "treeItem"; treeItem.innerHTML = data.name; div.appendChild(treeItem); if (data.children) { data.children.forEach(d => { createLi(d); }); }}val.forEach(v => { createLi(v);})
css样式
.treeItem > .treeItem{ padding-left: 10px; cursor: pointer;}.itemIcon { display: inline-block; width: 10px; height: 10px; border-radius: 50%; background: red; margin-right: 10px;}