原生 JS 实现页面树形(tree)菜单展示功能
# 简单的树结构
css 部分
.tree-box ul {
margin-left: 40px;
}
.tree-box ul li{
margin: 2px 0;
}
.tree-box ul li span{
margin-left: 5px;
}
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
html 部分
<div class="tree-box">
<ul id="treeBox"></ul>
</div>
1
2
3
2
3
JS 部分
function generate(menus, par, deep) {
for (let i = 0; i < menus.length; i++) {
let obj = menus[i];
obj.deep = deep
let ele = document.createElement('li');
if (obj.level === '1') {
ele.innerHTML = '●' + `<span>${obj.name}</span>`;
} else if (obj.level === '2') {
ele.innerHTML = '▲' + `<span>${obj.name}</span>`;
} else {
ele.innerHTML = '■' + `<span>${obj.name}</span>`;
}
if (obj.children) {
let nextpar = document.createElement('ul');
ele.appendChild(nextpar);
this.generate(obj.children, nextpar, deep + 1);
}
par.appendChild(ele);
}
};
// 使用
let datajson = {
name:"标题1",,
children:[{
name:"标题1-1",,
children:[{
}]
},{
name:"标题1-2",
children:[{
name:"标题1-2-1",,
}]
}]
}
generate([datajson], document.querySelector('#treeBox'), 0)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
# 菜单树结构
css 部分
/**
* DOM树
*/
ul>li{
list-style: none;
}
/* 可展开*/
.switch-open {
margin-left:-12px;
border:6px solid transparent;
display:inline-block;
width:0px;
height:0px;
border-top-color: black;
margin-right: 5px;
}
/* 展开完毕*/
.switch-close {
margin-left:-12px;
border:6px solid transparent;
display:inline-block;
width:0px;
height:0px;
border-left-color: black;
margin-bottom: 2px;
margin-right: 5px;
}
/* 改变CheckBox样式*/
input[type='checkbox']{
width: 20px;
height: 20px;
-webkit-appearance:none;
-moz-appearance: none;
border: 1px solid #c9c9c9;
border-radius: 3px;
outline: none;
color:white;
text-align: center;
margin-right: 5px;
}
input[type='checkbox']:before {
content: '√ ';
color:transparent;
}
input[type=checkbox]:checked{
background-color: #409eff;
}
input[type=checkbox]:checked:before{
content: '√';
color:white;
font-weight: bold;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
js 部分
//这里生成DOM
function generate(menus, par) {
for (var i = 0; i < menus.length; i++) {
var wzAuthority = menus[i];
var ele = document.createElement('li');
if(wzAuthority.children !== null && wzAuthority.children.length == 0) {
if (wzAuthority.checked) {
ele.innerHTML=' <input type="checkbox" οnclick="checkSingleChange(this)" checked="true" value="' + wzAuthority.id + '"></input>'+wzAuthority.authorityName;
} else {
ele.innerHTML=' <input type="checkbox" οnclick="checkSingleChange(this)" value="' + wzAuthority.id + '"></input>'+wzAuthority.authorityName;
}
// ele.innerHTML=' <input type="checkbox" οnclick="checkSingleChange(this)" value="' + wzAuthority.id + '"></input>'+wzAuthority.authorityName;
} else {
if (wzAuthority.checked) {
ele.innerHTML='<span><span class="switch-open" οnclick="toggle(this)"></span><input type="checkbox" checked="true" οnclick="checkChange(this)" value="' + wzAuthority.id + '"></input>' + wzAuthority.authorityName + '</span>';
} else {
ele.innerHTML='<span><span class="switch-open" οnclick="toggle(this)"></span><input type="checkbox" οnclick="checkChange(this)" value="' + wzAuthority.id + '"></input>' + wzAuthority.authorityName + '</span>';
}
// ele.innerHTML='<span><span class="switch-open" οnclick="toggle(this)"></span><input type="checkbox" οnclick="checkChange(this)" value="' + wzAuthority.id + '"></input>' + wzAuthority.authorityName + '</span>';
var nextpar = document.createElement('ul');
ele.appendChild(nextpar);
generate(wzAuthority.children, nextpar);
}
par.appendChild(ele);
}
}
//处理展开和收起
function toggle(eve) {
var par=eve.parentNode.nextElementSibling;
if(par.style.display=='none') {
par.style.display='block';
eve.className='switch-open';
} else {
par.style.display='none';
eve.className='switch-close';
}
}
//处理全部勾选和全部不选
function checkChange(eve) {
var oul = eve.parentNode.nextElementSibling;
var parent = oul.parentNode.firstChild.childNodes.item(1);
if(eve.checked) {
parent.setAttribute("checked", "true");
for(var i=0;i<oul.querySelectorAll('input').length;i++) {
if ("true" != oul.querySelectorAll('input')[i].getAttribute("checked")) {
oul.querySelectorAll('input')[i].setAttribute("checked", "true");
}
}
} else {
parent.setAttribute("checked","false");
console.log('当前元素---',oul)
for(var i=0;i<oul.querySelectorAll('input').length;i++) {
oul.querySelectorAll('input')[i].removeAttribute("checked");
}
}
}
//处理单个勾选和单个不选
function checkSingleChange(eve) {
console.log(eve)
if(eve.checked) {
eve.setAttribute("checked", "true");
//子元素选中,则父元素选中
console.log(eve.parentNode.parentNode.previousSibling.childNodes.item(1))
eve.parentNode.parentNode.previousSibling.childNodes.item(1).setAttribute("checked", "true");
} else {
eve.removeAttribute("checked");
//如果子元素全部清除,父元素也取消选中
for(var i=0;i<eve.parentNode.parentNode.querySelectorAll('input').length;i++) {
let inputElement = eve.parentNode.parentNode.querySelectorAll('input')[i];
if (inputElement.getAttribute("checked") == "true") {
return;
}
}
eve.parentNode.parentNode.previousSibling.childNodes.item(1).removeAttribute("checked");
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
html 部分
<div class="warp">
<ul id="container">
</ul>
</div>
1
2
3
4
2
3
4
使用部分
let dataJson = {
"menus": [
{
"id": "2",
"authorityName": "账号中心",
"type": 0,
"path": null,
"level": null,
"parentId": "0",
"isRequireAuth": null,
"createTime": null,
"updateTime": null,
"children": [
{
"id": "32",
"authorityName": "账号列表",
"type": 0,
"path": null,
"level": null,
"parentId": "2",
"isRequireAuth": null,
"createTime": null,
"updateTime": null,
"children": [
{
"id": "33",
"authorityName": "列表接口",
"type": 0,
"path": null,
"level": null,
"parentId": "32",
"isRequireAuth": null,
"createTime": null,
"updateTime": null,
"children": []
}
]
},
{
"id": "91",
"authorityName": "角色列表",
"type": 0,
"path": null,
"level": null,
"parentId": "2",
"isRequireAuth": null,
"createTime": null,
"updateTime": null,
"children": []
}
]
},
{
"id": "89",
"authorityName": "企业中心",
"type": 0,
"path": null,
"level": null,
"parentId": "0",
"isRequireAuth": null,
"createTime": null,
"updateTime": null,
"children": [
{
"id": "86",
"authorityName": "变更管理",
"type": 0,
"path": null,
"level": null,
"parentId": "89",
"isRequireAuth": null,
"createTime": null,
"updateTime": null,
"children": [
{
"id": "49",
"authorityName": "列表接口",
"type": 0,
"path": null,
"level": null,
"parentId": "86",
"isRequireAuth": null,
"createTime": null,
"updateTime": null,
"children": []
}
]
}
]
}
],
"checkedKeys": []
};
generate([dataJson], document.getElementById('container'));
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
上次更新: 2024/01/30, 00:35:17
- 02
- Node与GLIBC_2.27不兼容解决方案08-19
- 03
- Git清空本地文件跟踪缓存08-13