You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

修复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);

修正后的代码及说明

错误分析

  1. 缩进判断错误:原始文本用4个空格缩进,代码却匹配制表符(\t),无法正确识别层级
  2. 层级管理混乱:仅用单个currentUl变量无法处理多层嵌套,缺少层级回溯机制
  3. 冗余创建ul:给每个顶级li自动创建ul,即使没有子元素,不符合目标结构
  4. 未过滤空行:会生成无效的空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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.09 15:10:56