树形菜单是一种常见的网站导航方式,它通常由多个层级的菜单项组成,每个菜单项可以有子菜单项。在JavaScript中,我们可以使用递归函数来实现树形菜单。
树形菜单就是这样的东西,点击上一级,显示下一级,无限循环,一直逐层显示下一级。再次点击,关闭下一级。长的很像树,故名树形菜单。学会这个东西,是不是很酷?
树形菜单的主要作用是将信息层次化,将复杂的信息结构变得更加清晰和直观。它通常用于展示层级关系比较复杂的数据,如文件目录、网站导航、商品分类等。树形菜单的优点包括:
层次化展示:树形菜单可以将信息按照层级展示,使用户能够更加清晰地理解信息之间的关系。
简洁明了:树形菜单的结构简单明了,能够有效地减少信息的冗余,提高页面的整体美观度。
交互性强:树形菜单可以通过展开和收起节点的方式,使用户能够更加方便地获取所需信息。
可扩展性好:树形菜单可以根据需要随时添加新的节点,具有很好的扩展性。
首先,我们需要一个数据结构来表示树形菜单,通常可以使用嵌套的对象或数组来表示。每个菜单项包含以下属性:
下面是一个假数据:
const menu = [{
label: '家人',
children: [{
label: '爹妈',
children: [{
label: '我',
children: []
}]
}]
},
{
label: '老师',
children: [{
label: '物理老师',
children: [{
label: '物理老师儿子',
children: []
}]
},
{
label: '化学老师',
children: [{
label: '化学老师儿子',
children: []
}]
}
]
},
{
label: '老板',
children: [{
label: '总经理',
children: [{
label: '领导1',
children: [{
label: '韩国分公司',
children: []
}]
},
{
label: '领导2',
children: [{
label: '日本分公司',
children: []
}]
}
]
}]
}
];
接下来,我们可以定义一个递归函数来遍历这个数据源,并且为每个菜单项添加点击事件。
下面是一个递归函数实现:
function createMenu(menuData) {
const menuEl = document.createElement('ul');
menuData.forEach(item => {
const itemEl = document.createElement('li');
const labelEl = document.createElement('span');
labelEl.innerText = item.label;
itemEl.appendChild(labelEl);
if (item.children.length > 0) {
labelEl.addEventListener('click', () => {
if (itemEl.classList.contains('open')) {
itemEl.classList.remove('open');
itemEl.removeChild(itemEl.lastChild);
} else {
itemEl.classList.add('open');
const submenuEl = createMenu(item.children);
itemEl.appendChild(submenuEl);
}
});
}
menuEl.appendChild(itemEl);
});
return menuEl;
}
最后,我们可以调用这个函数来生成完整的树形菜单的HTML代码:
const menuEl = createMenu(menu);
document.body.appendChild(menuEl);
这里假设树形菜单的容器元素的ID为menu。我们先取出这个元素,然后将生成的HTML代码插入到这个元素的innerHTML属性中,即可显示出树形菜单。
DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>title>
<script src="./js/jquery-3.6.1.js">script>
<style>style>
head>
<body>
<script>
const menu = [{
label: '家人',
children: [{
label: '爹妈',
children: [{
label: '我',
children: []
}]
}]
},
{
label: '老师',
children: [{
label: '物理老师',
children: [{
label: '物理老师儿子',
children: []
}]
},
{
label: '化学老师',
children: [{
label: '化学老师儿子',
children: []
}]
}
]
},
{
label: '老板',
children: [{
label: '总经理',
children: [{
label: '领导1',
children: [{
label: '韩国分公司',
children: []
}]
},
{
label: '领导2',
children: [{
label: '日本分公司',
children: []
}]
}
]
}]
}
];
function createMenu(menuData) {
const menuEl = document.createElement('ul');
menuData.forEach(item => {
const itemEl = document.createElement('li');
const labelEl = document.createElement('span');
labelEl.innerText = item.label;
itemEl.appendChild(labelEl);
if (item.children.length > 0) {
labelEl.addEventListener('click', () => {
if (itemEl.classList.contains('open')) {
itemEl.classList.remove('open');
itemEl.removeChild(itemEl.lastChild);
} else {
itemEl.classList.add('open');
const submenuEl = createMenu(item.children);
itemEl.appendChild(submenuEl);
}
});
}
menuEl.appendChild(itemEl);
});
return menuEl;
}
const menuEl = createMenu(menu);
document.body.appendChild(menuEl);
script>
body>
html>