js实现四层树形菜单
实现思路
四层树形菜单可以通过递归或迭代方式生成,数据结构通常采用嵌套对象或数组。核心逻辑是动态渲染DOM节点,并通过CSS控制展开/折叠效果。

数据结构示例
const treeData = [
{
label: '一级菜单1',
children: [
{
label: '二级菜单1-1',
children: [
{
label: '三级菜单1-1-1',
children: [
{ label: '四级菜单1-1-1-1' },
{ label: '四级菜单1-1-1-2' }
]
}
]
}
]
}
];
递归渲染方法
function renderTree(data, container) {
const ul = document.createElement('ul');
data.forEach(item => {
const li = document.createElement('li');
const span = document.createElement('span');
span.textContent = item.label;
li.appendChild(span);
if (item.children) {
span.classList.add('has-children');
span.addEventListener('click', function() {
this.parentElement.classList.toggle('expanded');
});
renderTree(item.children, li);
}
ul.appendChild(li);
});
container.appendChild(ul);
}
// 调用方式
const menuContainer = document.getElementById('menu');
renderTree(treeData, menuContainer);
CSS样式建议
ul {
list-style: none;
padding-left: 20px;
}
li {
cursor: pointer;
margin: 5px 0;
}
.has-children::before {
content: '+ ';
color: #666;
}
li.expanded > .has-children::before {
content: '- ';
}
li > ul {
display: none;
}
li.expanded > ul {
display: block;
}
动态加载优化
对于大型树形结构,可采用懒加载方式:
span.addEventListener('click', async function() {
if (!this.parentElement.classList.contains('loaded') && item.childrenUrl) {
const res = await fetch(item.childrenUrl);
item.children = await res.json();
renderTree(item.children, this.parentElement);
this.parentElement.classList.add('loaded');
}
this.parentElement.classList.toggle('expanded');
});
交互增强方案
添加键盘导航支持:
menuContainer.addEventListener('keydown', (e) => {
const focused = document.activeElement;
if (e.key === 'ArrowRight') {
focused.parentElement.classList.add('expanded');
}
if (e.key === 'ArrowLeft') {
focused.parentElement.classList.remove('expanded');
}
});
性能注意事项
- 超过1000个节点时建议使用虚拟滚动
- 深层嵌套样式需注意选择器性能
- 频繁更新的场景建议使用文档片段(documentFragment)







