修复JavaScript代码以生成层级树形列表的技术求助
问题:将缩进文本转换为树形列表结构
需求说明
需要把body元素内的带缩进文本,转换成指定结构的嵌套<ul>树形列表。
原始body文本内容
<body> Parent 1 Parent 2 Parent 3 1st Child of 3 1st grandchild 2nd grandchild 2nd Child of 3 3rd Child of 3 Parent 4 Parent 4's only child </body>
目标树形列表结构
<ul class="tree"> <li>Parent 1</li> <li>Parent 2</li> <li> Parent 3 <ul> <li> 1st Child of 3 <ul> <li>1st grandchild</li> <li>2nd grandchild</li> </ul> </li> <li>2nd Child of 3</li> <li>3rd Child of 3</li> </ul> </li> <li> Parent 4 <ul> <li>Parent 4's only child</li> </ul> </li> </ul>
用户尝试的问题代码
var bodyElement = document.body; var bodyText = bodyElement.textContent; bodyElement.textContent = ''; var outputDiv = document.createElement('div'); outputDiv.id = 'output'; document.body.appendChild(outputDiv); var outputElement = document.getElementById('output'); var lines = bodyText.split('\n'); var ul = document.createElement('ul'); ul.classList.add('tree'); // Přidáme třídu "tree" k ul elementu var currentUl = ul; var currentLi = null; for (var i = 0; i < lines.length; i++) { var line = lines[i]; var indent = line.match(/^\t*/)[0].length; // Zjistíme počet tabulátorů na začátku řádku var li = document.createElement('li'); var span = document.createElement('span'); span.textContent = line.trim(); // Odstraníme bílé znaky na začátku a konci řádku li.appendChild(span); if (indent === 0) { if (currentLi) { currentUl.appendChild(currentLi); } currentLi = li; ul.appendChild(currentLi); currentUl = document.createElement('ul'); currentLi.appendChild(currentUl); } else { if (currentLi) { currentUl.appendChild(currentLi); } currentLi = li; } } if (currentLi) { currentUl.appendChild(currentLi); } outputElement.appendChild(ul);
修正后的代码及说明
错误分析
- 缩进判断错误:原始文本用4个空格缩进,代码却匹配制表符(
\t),无法正确识别层级 - 层级管理混乱:仅用单个
currentUl变量无法处理多层嵌套,缺少层级回溯机制 - 冗余创建ul:给每个顶级li自动创建ul,即使没有子元素,不符合目标结构
- 未过滤空行:会生成无效的空li元素
修正代码
// 获取body文本并清空原内容 const bodyElement = document.body; const bodyText = bodyElement.textContent; bodyElement.textContent = ''; // 创建输出容器 const outputDiv = document.createElement('div'); outputDiv.id = 'output'; bodyElement.appendChild(outputDiv); // 处理文本行:过滤空行,只保留有效内容 const lines = bodyText.split('\n').filter(line => line.trim() !== ''); const rootUl = document.createElement('ul'); rootUl.classList.add('tree'); // 层级栈:保存每个层级对应的ul元素,初始存入根ul const levelStack = [rootUl]; for (const line of lines) { // 计算缩进层级:每4个空格对应1级 const indentSpaces = line.match(/^\s*/)[0].length; const currentLevel = Math.floor(indentSpaces / 4); // 创建当前li元素 const li = document.createElement('li'); li.textContent = line.trim(); // 调整层级栈:确保栈顶是当前层级的父ul while (levelStack.length > currentLevel + 1) { levelStack.pop(); } // 将li添加到当前层级的父ul中 const parentUl = levelStack[levelStack.length - 1]; parentUl.appendChild(li); // 为当前li创建子ul,推入栈中供后续子元素使用 const childUl = document.createElement('ul'); li.appendChild(childUl); levelStack.push(childUl); } // 移除空的ul(没有子元素的冗余ul) const emptyUls = rootUl.querySelectorAll('ul:empty'); emptyUls.forEach(ul => ul.remove()); // 将最终树形结构添加到输出容器 outputDiv.appendChild(rootUl);
关键修正点
- 适配空格缩进:按每4个空格对应一个层级,匹配原始文本的缩进规则
- 层级栈管理:通过栈维护当前所在层级的ul,嵌套时推入、回退时弹出,精准控制父容器
- 清理冗余标签:最后移除没有子元素的ul,避免无效标签
- 过滤空行:跳过无效的空文本行,避免生成空节点
内容的提问来源于stack exchange,提问作者Host
相关产品推荐
相关产品推荐

