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

如何将生成目录列表的JS函数转换为React JSX元素?

把标题层级数组转成React JSX元素的解决方案

嘿,我明白你不想用dangerouslySetInnerHTML的心情,毕竟这种方式既不安全也不符合React的最佳实践。咱们直接把第二个函数改成递归生成JSX的版本,完全贴合你习惯的数组映射写法~

先回顾下你的原有代码

1. 解析HTML标题为层级数组的函数

这个函数可以保留,它生成的层级数组是咱们后续处理的基础:

const str = "<h1>test-1<h1><h2>test1-1<h2><h3>test1-1-1</h3><h1>test1-2<h1><h2>test1-2-1</h2><h3>test1-2-2</h3><h1>test-2</h1><h1>test-3</h1><h1>test-4</h1> "
const wrapper = document.createElement('div');
wrapper.innerHTML = str.trim();
let tree = [];
let leaf = null;
for (const node of wrapper.querySelectorAll("h1, h2, h3, h4, h5, h6")) {
  const nodeLevel = parseInt(node.tagName[1]);
  const newLeaf = { level: nodeLevel, text: node.textContent, children: [], parent: leaf };
  while (leaf && newLeaf.level <= leaf.level) leaf = leaf.parent;
  if (!leaf) tree.push(newLeaf);
  else leaf.children.push(newLeaf);
  leaf = newLeaf;
}

2. 原有的生成HTML列表的函数

原来的函数是生成DOM元素再转成HTML字符串,咱们要替换掉它:

const ol = document.createElement("ol");
(function makeOl(ol, leaves) {
  for (const leaf of leaves) {
    const li = document.createElement("li");
    li.appendChild(new Text(leaf.text));
    if (leaf.children.length > 0) {
      const subOl = document.createElement("ol");
      makeOl(subOl, leaf.children);
      li.appendChild(subOl);
    }
    ol.appendChild(li);
  }
})(ol, tree);

你之前想要避免的不安全写法:

<div dangerouslySetInnerHTML={{__html: olString}} />

而你偏好的数组映射生成JSX的方式:

const list = tree.map((headers) => <li>{headers.value}</li>)
<div><ul>{list}</ul></div>

改造后的React JSX版本

咱们写一个递归的函数,直接生成React元素,完美适配你的习惯:

// 递归生成目录列表的JSX组件
const renderToc = (leaves) => {
  return (
    <ol>
      {leaves.map((leaf, index) => (
        <li key={index}>
          {leaf.text}
          {/* 有子节点就递归渲染子列表 */}
          {leaf.children.length > 0 && renderToc(leaf.children)}
        </li>
      ))}
    </ol>
  );
};

这里有几个关键点:

  • 用map遍历每个层级节点,完全符合你熟悉的写法
  • 给每个<li>加上key(React列表元素必须有唯一标识,这里用index是简单方案,如果你的标题有唯一ID之类的,用那个会更稳定)
  • 递归调用renderToc处理子节点,自动生成嵌套的<ol>结构

实际用法示例

在你的React组件里直接调用这个函数就行:

function TocComponent() {
  // 假设你已经通过第一个函数生成了tree数组
  const tree = /* 你的层级数组数据 */;
  
  return (
    <div className="toc-container">
      {/* 直接渲染生成的JSX */}
      {renderToc(tree)}
    </div>
  );
}

这样生成的都是React原生的JSX元素,完全不需要依赖dangerouslySetInnerHTML,既安全又符合React的开发模式~

内容的提问来源于stack exchange,提问作者totalnoob

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 09:34:27