
本文详解如何基于嵌套 json 数据,通过纯 javascript 递归渲染出语义清晰、层级分明的文件夹树形结构,并配合轻量 css 实现缩进与视觉对齐,无需框架即可实现可扩展的前端目录视图。
本文详解如何基于嵌套 json 数据,通过纯 javascript 递归渲染出语义清晰、层级分明的文件夹树形结构,并配合轻量 css 实现缩进与视觉对齐,无需框架即可实现可扩展的前端目录视图。
在构建文档管理、资源导航或配置可视化等前端应用时,将层级化的文件夹数据(如目录树)动态渲染为 HTML 结构是常见需求。核心挑战在于:如何将任意深度的嵌套对象,准确映射为具有正确父子关系和样式嵌套的 DOM 节点? 答案是——使用递归函数 + 元素工厂模式。
以下是一个完整、可直接运行的实现方案,包含结构化 HTML 模板、精简 CSS 样式和健壮的 JavaScript 渲染逻辑。
✅ 基础 HTML 结构(静态容器)
首先,确保页面中存在一个挂载点(如 .tree 容器),JavaScript 将在此处注入树形 DOM:
<div class="static-page">
<div class="container">
<div class="tree"></div> <!-- 渲染入口 -->
</div>
</div>✅ 样式定义(支持无限嵌套缩进)
仅需一行关键 CSS 即可实现层级缩进,避免冗余类名或 JS 计算:
立即学习“Java免费学习笔记(深入)”;
.children-list {
padding-left: 12px;
}该规则利用 CSS 的层叠特性:每深入一层 children-list,就叠加一次 12px 左侧内边距,天然适配任意深度。
✅ JavaScript 渲染逻辑(递归 + 元素工厂)
我们封装两个核心函数:
- makeEl(tag, props):安全创建并配置元素(避免重复 document.createElement);
- walk(parent, node):递归遍历节点,为每个文件夹生成 标题行,并在其下挂载子列表(.children-list)及子项(.children-item)。
const data = { name: "Root", children: [ { name: "Folder 1", children: [ { name: "Folder 1-1" }, { name: "Folder 1-2" } ] }, { name: "Folder 2", children: [ { name: "Folder 2-1" }, { name: "Folder 2-2" } ] } ] }; // ✅ 元素工厂:统一创建 & 属性赋值 function makeEl(tag, props) { const el = document.createElement(tag); Object.assign(el, props); // 支持 innerText, className, id 等原生属性 return el; } // ✅ 递归渲染器:parent 为插入目标,node 为当前节点数据 function walk(parent, node) { // 创建标题行:图标 + 名称 const titleEl = makeEl("div", { className: "flex items-center gap-x-12 font-bold" }); titleEl.appendChild(makeEl("span", { innerText: "−" })); titleEl.appendChild(makeEl("span", { innerText: node.name })); parent.appendChild(titleEl); // 若有子节点,创建子列表容器并递归渲染 if (Array.isArray(node.children) && node.children.length > 0) { const listEl = makeEl("div", { className: "children-list" }); parent.appendChild(listEl); for (const child of node.children) { const itemEl = makeEl("div", { className: "children-item" }); listEl.appendChild(itemEl); walk(itemEl, child); // 递归调用,深度优先 } } } // ? 启动渲染:将 data 挂载到 .tree 容器 document.addEventListener("DOMContentLoaded", () => { const treeRoot = document.querySelector(".tree"); if (treeRoot) { walk(treeRoot, data); } else { console.error("❌ Missing element with class '.tree'"); } });⚠️ 注意事项与最佳实践
- 空数据防护:walk() 中使用 Array.isArray(node.children) 替代 node.children && node.children.length,避免 null/undefined 或非数组类型引发错误;
- 性能考虑:对于超深或超大目录(>1000 节点),建议添加节流、虚拟滚动或懒加载(点击展开)机制;
- 可访问性增强:可为 .flex 行添加 role="treeitem",为 .children-list 添加 role="group",并配合 aria-expanded 实现无障碍支持;
- 样式解耦建议:.flex, .items-center, .gap-x-12 等类名源自 Tailwind CSS;若未使用,可替换为自定义类(如 .folder-row, .indent-1)并补充对应 CSS 规则。
✅ 总结
本方案以语义清晰、零依赖、易维护为设计原则:
✅ 使用纯原生 API,兼容所有现代浏览器;
✅ 递归逻辑简洁直观,易于调试与扩展(如添加图标、复选框、拖拽事件);
✅ CSS 仅靠 padding-left 实现缩进,无硬编码层级,天然支持无限嵌套;
✅ 支持任意结构的树形数据,只需保持 { name, children: [] } 格式即可复用。将上述代码整合后,即可获得一个轻量、可靠、专业级的前端文件夹树渲染模块。



















