JavaScript遍历嵌套对象构建目录优先排序文件树的问题修复
问题根源
原代码存在三个核心问题导致渲染顺序、层级错误:
- 遍历对象属性时未做分类和排序:
Object.keys()返回的属性顺序不保证符合业务要求,原代码遍历到files属性就直接渲染文件,导致文件排在目录前面,既没有满足「目录在前、文件在后」的规则,也没有对同层级内容做字母排序。 - 全局
iterations计数器控制标签闭合的逻辑完全错误:递归渲染的HTML标签必须和递归层级一一对应,开标签和闭标签成对出现,靠全局变量增减计数控制闭合,会导致闭标签位置完全错乱,嵌套层级混乱。 - 没有对同层级的目录、文件分别做排序处理。
修复实现
核心处理逻辑:
- 每一层递归处理目录节点时,先把当前节点内容拆成两类:子目录(属性值为对象、属性名不是
files)、当前目录下的文件(files数组内容) - 对子目录名称、文件名称分别做字母升序排序
- 渲染顺序固定为先渲染所有排序后的子目录,再渲染所有排序后的文件
- 每个子目录递归渲染完内部内容后,立刻闭合当前目录对应的
</ul></li>标签,和开标签一一对应,完全删除全局计数器逻辑,从根源避免层级错乱。
完整可运行代码:
let html = ''; // 原始文件数据 const fileData = { "files": ["index.html","panel.html"], "directory1": { "files": ["foo.html"], "subdir1": { "files": ["somefile.txt"] }, "subdir2": { "files": ["somefile.php","other.php"] } }, "directory2": { "subdir1": { "files": ["you_get_the_idea.txt"] } } }; // 字母升序排序方法,需要不区分大小写可以改为a.localeCompare(b.toLowerCase(), b.toLowerCase()) const sortAlpha = (a, b) => a.localeCompare(b); const renderFileTree = (currentNode) => { const subDirectories = []; let currentFiles = []; // 拆分当前节点的子目录和文件 Object.keys(currentNode).forEach(key => { if (key === 'files') { currentFiles = Array.isArray(currentNode[key]) ? currentNode[key] : []; return; } if (typeof currentNode[key] === 'object' && currentNode[key] !== null) { subDirectories.push(key); } }); // 分别排序 subDirectories.sort(sortAlpha); currentFiles.sort(sortAlpha); // 先渲染排序后的目录 subDirectories.forEach(dirName => { html += `<li><input type="checkbox"/><span>${dirName}</span><ul>`; renderFileTree(currentNode[dirName]); // 递归完成后直接闭合当前目录标签,和开标签严格对应 html += '</ul></li>'; }); // 再渲染排序后的文件 currentFiles.forEach(fileName => { html += `<li><span>${fileName}</span></li>`; }); }; // 根节点外层包裹ul标签 html = '<ul class="file-tree">'; renderFileTree(fileData); html += '</ul>'; // 插入到页面对应容器即可 document.querySelector('#file-tree-container').innerHTML = html;
渲染后的正确结构如下(注:你给出的期望示例有误,根目录下的directory2和directory1同级,不属于subdir2的子内容):
- directory1 -- foo.html -- subdir1 --- somefile.txt -- subdir2 --- other.php --- somefile.php - directory2 -- subdir1 --- you_get_the_idea.txt - index.html - panel.html
内容的提问来源于stack exchange,提问作者icecub
相关产品推荐
相关产品推荐

