js实现树形菜单
实现树形菜单的基本思路
树形菜单通常由嵌套的列表结构构成,通过JavaScript动态生成HTML元素并控制其展开/折叠状态。核心逻辑包括数据结构的定义、DOM操作和事件绑定。
数据结构设计
树形菜单的数据通常以嵌套对象或数组表示,每个节点包含id、label、children等属性。例如:
const treeData = [
{
id: 1,
label: "节点1",
children: [
{
id: 2,
label: "子节点1",
children: []
}
]
}
];
递归渲染树形结构
通过递归函数遍历数据并生成对应的HTML元素:
function renderTree(node, parentElement) {
const li = document.createElement('li');
li.innerHTML = `<span>${node.label}</span>`;
if (node.children && node.children.length > 0) {
const ul = document.createElement('ul');
node.children.forEach(child => renderTree(child, ul));
li.appendChild(ul);
}
parentElement.appendChild(li);
}
添加展开/折叠功能
为每个可展开的节点添加点击事件,通过CSS类控制子菜单的显示/隐藏:
li.querySelector('span').addEventListener('click', function() {
const ul = this.parentNode.querySelector('ul');
if (ul) ul.classList.toggle('hidden');
});
对应的CSS样式:
.hidden { display: none; }
完整实现示例
document.addEventListener('DOMContentLoaded', function() {
const treeData = [
{
id: 1,
label: "根节点",
children: [
{
id: 2,
label: "子节点1",
children: [
{ id: 3, label: "子子节点1", children: [] }
]
},
{ id: 4, label: "子节点2", children: [] }
]
}
];
const treeContainer = document.getElementById('tree');
treeData.forEach(node => renderTree(node, treeContainer));
function renderTree(node, parentElement) {
const li = document.createElement('li');
const span = document.createElement('span');
span.textContent = node.label;
li.appendChild(span);
if (node.children && node.children.length > 0) {
const ul = document.createElement('ul');
node.children.forEach(child => renderTree(child, ul));
li.appendChild(ul);
span.addEventListener('click', function(e) {
e.stopPropagation();
ul.classList.toggle('hidden');
});
}
parentElement.appendChild(li);
}
});
使用第三方库简化开发
如果需要更复杂的功能(如拖拽、复选框等),可以考虑使用现成的树形菜单库:
-
jsTree:功能丰富的jQuery插件
$('#tree').jstree({ 'core': { 'data': treeData } }); -
zTree:轻量级的纯JavaScript实现
-
Vue/React生态:

- Vue:
vue-treeselect - React:
react-treebeard
- Vue:






