js实现树表
实现树表的基本思路
使用JavaScript实现树表(Tree Table)通常涉及将层级数据渲染为可展开/折叠的表格结构。核心步骤包括数据建模、DOM渲染和交互逻辑处理。
数据结构设计
树表数据通常为嵌套结构,每个节点包含自身数据和子节点数组:
const treeData = [
{
id: 1,
name: 'Parent 1',
children: [
{ id: 11, name: 'Child 1.1' },
{ id: 12, name: 'Child 1.2' }
]
}
];
递归渲染方法
通过递归函数渲染树形结构,需处理缩进和展开状态:
function renderTreeTable(data, level = 0, parentId = '') {
return data.map(item => {
const hasChildren = item.children && item.children.length > 0;
const rowId = parentId ? `${parentId}-${item.id}` : item.id;
return `
<tr data-id="${rowId}" data-level="${level}">
<td style="padding-left: ${level * 20}px">
${hasChildren ?
`<button class="toggle" data-target="${rowId}">+</button>` :
'<span class="indent"></span>'}
${item.name}
</td>
<!-- 其他列数据 -->
</tr>
${hasChildren ? renderTreeTable(item.children, level + 1, rowId) : ''}
`;
}).join('');
}
交互逻辑实现
绑定点击事件处理展开/折叠功能:
document.addEventListener('click', (e) => {
if (e.target.classList.contains('toggle')) {
const targetId = e.target.getAttribute('data-target');
const rows = document.querySelectorAll(`tr[data-id^="${targetId}-"]`);
rows.forEach(row => {
row.style.display = row.style.display === 'none' ? '' : 'none';
});
e.target.textContent = e.target.textContent === '+' ? '-' : '+';
}
});
完整示例代码
结合上述逻辑的完整实现示例:
class TreeTable {
constructor(containerId, data) {
this.container = document.getElementById(containerId);
this.data = data;
this.render();
}
render() {
this.container.innerHTML = `
<table>
<thead><tr><th>Name</th></tr></thead>
<tbody>${this.renderRows(this.data)}</tbody>
</table>
`;
this.bindEvents();
}
renderRows(data, level = 0, parentId = '') {
return data.map(item => {
const hasChildren = item.children?.length > 0;
const rowId = parentId ? `${parentId}-${item.id}` : item.id;
return `
<tr data-id="${rowId}" data-level="${level}">
<td style="padding-left: ${level * 20}px">
${hasChildren ?
`<button class="toggle" data-target="${rowId}">+</button>` :
'<span class="indent"></span>'}
${item.name}
</td>
</tr>
${hasChildren ? this.renderRows(item.children, level + 1, rowId) : ''}
`;
}).join('');
}
bindEvents() {
this.container.addEventListener('click', (e) => {
if (e.target.classList.contains('toggle')) {
this.toggleRow(e.target);
}
});
}
toggleRow(button) {
const targetId = button.getAttribute('data-target');
const rows = this.container.querySelectorAll(`tr[data-id^="${targetId}-"]`);
rows.forEach(row => {
row.style.display = row.style.display === 'none' ? '' : 'none';
});
button.textContent = button.textContent === '+' ? '-' : '+';
}
}
// 使用示例
new TreeTable('treeTableContainer', treeData);
性能优化建议
对于大型树结构,考虑以下优化方案:
- 虚拟滚动:只渲染可视区域内的节点
- 懒加载:动态加载子节点数据
- 使用文档片段(DocumentFragment)减少DOM操作次数
样式增强建议
通过CSS改善视觉效果:
.tree-table tr[data-level] > td {
border-left: 1px dotted #ccc;
}
.toggle {
cursor: pointer;
background: none;
border: none;
width: 20px;
text-align: center;
}
.indent {
display: inline-block;
width: 20px;
}
第三方库推荐
如需快速实现,可考虑现成解决方案:
- jsTree:支持表格集成的树插件
- AG Grid:企业级表格组件含树形展示功能
- D3.js:数据驱动文档的复杂树形可视化







