本文详解如何使用递归 JavaScript 函数,将符合语义嵌套规则的 <ul> <li> 结构(如操作符/条件树)精准转换为等价的嵌套数组,支持无限深度,并正确保留层级关系与文本内容。
本文详解如何使用递归 javascript 函数,将符合语义嵌套规则的 `
- ` `
- ` 结构(如操作符/条件树)精准转换为等价的嵌套数组,支持无限深度,并正确保留层级关系与文本内容。
在构建动态规则引擎、可视化逻辑编辑器或配置化表单系统时,常需将 DOM 中嵌套的 <ul> <li> 结构(例如表示“操作符→子操作符/条件”的树形逻辑)序列化为可编程处理的嵌套数组。关键挑战在于:每个 <li> 可能自身携带文本内容,其后紧跟一个可选的 <ul> 子列表;该子列表应作为当前项的子数组,而非独立兄弟节点。
以下是一个健壮、简洁且符合实际 HTML 结构的解析方案:
✅ 正确的 HTML 结构前提
首先需确保原始 HTML 符合标准嵌套规范(即 <ul> 必须直接包裹 <li>,子 <ul> 应位于 <li> 内部,而非平级):
<ul> <li class="operator">operator1 <ul> <li class="operator">operator2 <ul> <li class="condition">condition1</li> <li class="condition">condition2</li> </ul> </li> <li class="condition">condition3</li> </ul> </li> </ul>⚠️ 注意:原问题中 <ul> 平级出现在 <li> 外部是非法 HTML,会导致 querySelectorAll('li') 获取错乱层级。解析函数依赖合法 DOM 树结构——子 <ul> 是 <li> 的后代(通常为直接子元素),而非同级元素。
立即学习“前端免费学习笔记(深入)”;
✅ 递归解析实现
const parseListItems = (element) => { const resultArray = []; // 遍历 element 的直接子元素(避免误抓文本节点) Array.from(element.children).forEach(child => { if (child.tagName === 'LI') { const textContent = child.textContent.trim(); const nestedUl = child.querySelector('ul'); if (nestedUl) { // 当前 li 包含子 ul → 生成 [text, ...nestedArray] const nestedResult = parseListItems(nestedUl); resultArray.push([textContent, ...nestedResult]); } else { // 无子 ul → 直接推入纯文本 resultArray.push(textContent); } } }); return resultArray; }; // 使用示例 document.addEventListener('DOMContentLoaded', () => { const rootUl = document.querySelector('ul'); const tree = parseListItems(rootUl); console.log(tree); // 输出: ["operator1", ["operator2", ["condition1"], ["condition2"]], "condition3"] });? 关键设计说明
- element.children 而非 querySelectorAll('li'):确保只遍历当前层级的 <li>,避免跨层污染;
- child.textContent.trim():安全提取可见文本(兼容含内联标签的 <li>,如 <li><span>op</span></li>);
- [textContent, ...nestedResult]:显式构造 [父文本, 子数组1, 子数组2, ...],严格匹配目标格式;
- 递归边界自然清晰:无 <ul> 则终止递归,返回纯字符串;有则继续下探。
? 注意事项
- 若 <li> 内含多个文本节点或复杂结构(如图标、按钮),建议改用 child.querySelector('.content')?.textContent 或预处理 DOM;
- 如需保留 class 信息(如区分 "operator" 与 "condition"),可扩展为对象形式:{ type: 'operator', value: 'operator1', children: [...] };
- 浏览器兼容性良好(ES5+),无需额外 polyfill。
该方案以最小侵入性、最大可读性,将 HTML 列表语义无损映射为 JavaScript 数据结构,是前端树形数据序列化的典型实践。



















