先上個效果圖
獲取到的數據是這樣的
[
{ id: 1, text: '一級菜單A', parentId: null },
{ id: 2, text: '一級菜單B', parentId: null },
{ id: 3, text: '一級菜單C', parentId: null },
{ id: 4, text: '二級菜單AA', parentId: 1 },
{ id: 5, text: '二級菜單AB', parentId: 1 },
{ id: 6, text: '二級菜單AC', parentId: 1 },
{ id: 7, text: '二級菜單BA', parentId: 2 },
{ id: 8, text: '二級菜單BB', parentId: 2 },
{ id: 9, text: '二級菜單BC', parentId: 2 },
{ id: 10, text: '二級菜單CA', parentId: 3 },
{ id: 11, text: '二級菜單CB', parentId: 3 },
{ id: 12, text: '二級菜單CC', parentId: 3 },
{ id: 13, text: '三級菜單AAA', parentId: 4 },
{ id: 14, text: '三級菜單BAA', parentId: 7 },
{ id: 15, text: '三級菜單CAA', parentId: 10 }
]
那如何將這些數據轉化為樹狀結構並渲染出來
先上完整代碼
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<style>
ul,
li {
list-style: none;
}
</style>
</head>
<body>
<div class="nav">
</div>
</body>
<script>
// 數據
let navData = [
{ id: 1, text: '一級菜單A', parentId: null },
{ id: 2, text: '一級菜單B', parentId: null },
{ id: 3, text: '一級菜單C', parentId: null },
{ id: 4, text: '二級菜單AA', parentId: 1 },
{ id: 5, text: '二級菜單AB', parentId: 1 },
{ id: 6, text: '二級菜單AC', parentId: 1 },
{ id: 7, text: '二級菜單BA', parentId: 2 },
{ id: 8, text: '二級菜單BB', parentId: 2 },
{ id: 9, text: '二級菜單BC', parentId: 2 },
{ id: 10, text: '二級菜單CA', parentId: 3 },
{ id: 11, text: '二級菜單CB', parentId: 3 },
{ id: 12, text: '二級菜單CC', parentId: 3 },
{ id: 13, text: '三級菜單AAA', parentId: 4 },
{ id: 14, text: '三級菜單BAA', parentId: 7 },
{ id: 15, text: '三級菜單CAA', parentId: 10 }
];
// let nav = document.getElementsByClassName('nav')
let nav = document.querySelector('.nav')
// 將數組置為樹形
let treeee = (function makeTreeData(arr, parentId) {
let temp = []
for (let i = 0; i < arr.length; i++) {
if (arr[i].parentId === parentId) {
temp.push(arr[i])
arr[i].children = makeTreeData(navData, arr[i].id)
}
}
return temp
})(navData, null)
console.log(treeee);
// 創造dom樹
(function makeDomTree(data, node) {
let ul
for (let i = 0; i < data.length; i++) {
ul = document.createElement('ul')
let li = document.createElement('li')
li.innerHTML = data[i].text
node.appendChild(ul)
ul.appendChild(li)
if (data[i].children.length !== 0) {
let element = makeDomTree(data[i].children, ul)
ul.appendChild(element)
}
}
return ul
})(treeee, nav)
</script>
</html>
分為兩步
解析
第一步將數據進行轉化
需要將數據轉化為如下格式
[
{ id: 1,
text: '一級菜單A',
parentId: null ,
children:[
{ id: 4, text: '二級菜單AA', parentId: 1 ,children[{ id: 13, text: '三級菜單AAA', parentId: 4,children:[] }]},
{ id: 5, text: '二級菜單AB', parentId: 1 ,children[]},
{ id: 6, text: '二級菜單AC', parentId: 1 ,children[]}
]
},
...
]
也就是說可以利用children屬性讓我們很清楚的看到,每個菜單的子菜單有多少項並包含着每項子菜單的每個屬性
代碼時這樣子的,利用遞歸算法直接構建數據
let treeee = (function makeTreeData(arr, parentId) {
let temp = []
for (let i = 0; i < arr.length; i++) {
if (arr[i].parentId === parentId) {
temp.push(arr[i])
arr[i].children = makeTreeData(navData, arr[i].id)
}
}
return temp
})(navData, null)
console.log(treeee);
第二步將數據渲染至頁面
let nav = document.querySelector('.nav')
(function makeDomTree(data, node) {
let ul //創建一個ul節點
for (let i = 0; i < data.length; i++) {
ul = document.createElement('ul')
let li = document.createElement('li')
li.innerHTML = data[i].text
node.appendChild(ul)
ul.appendChild(li)
//以上幾步是將當前數組的每個項都作為一個li放置到ul中
//若有子項進行遞歸操作
if (data[i].children.length !== 0) {
let element = makeDomTree(data[i].children, ul)
ul.appendChild(element)
}
}
return ul //返回ul節點
})(treeee, nav) //treeee是之前構建好的數據