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

如何在React中不使用dangerouslySetInnerHTML或第三方包渲染字符串HTML?

不依赖第三方包直接渲染HTML字符串为React元素的方案

如果你不想用dangerouslySetInnerHTML的外层包裹,也不想依赖第三方库,可以自己实现一个HTML字符串转React元素的解析函数,核心思路是利用浏览器的DOMParser解析HTML,再递归将DOM节点转换成React元素。

实现步骤

  • 使用DOMParser将HTML字符串解析为DOM树
  • 递归遍历DOM节点,将每个节点转换为对应的React元素:
    • 处理元素节点:提取标签名、属性(注意转换class为className,解析style为对象等)
    • 处理文本节点:直接返回文本内容
    • 处理注释节点:按需忽略或保留

具体实现代码

function htmlStringToReactElement(htmlStr) {
  const parser = new DOMParser();
  const doc = parser.parseFromString(htmlStr, 'text/html');
  const rootNode = doc.body.firstChild;

  if (!rootNode) return null;

  const convertNode = (node) => {
    // 处理文本节点
    if (node.nodeType === Node.TEXT_NODE) {
      return node.textContent.trim() || null;
    }

    // 处理元素节点
    if (node.nodeType === Node.ELEMENT_NODE) {
      const tagName = node.tagName.toLowerCase();
      const attributes = {};

      // 遍历所有属性
      for (const attr of node.attributes) {
        const attrName = attr.name;
        const attrValue = attr.value;

        // 转换class为className
        if (attrName === 'class') {
          attributes.className = attrValue;
        }
        // 解析style为React支持的对象格式
        else if (attrName === 'style') {
          attributes.style = attrValue.split(';').reduce((styleObj, style) => {
            const [key, value] = style.split(':').map(s => s.trim());
            if (key && value) {
              // 转换为驼峰式属性名,比如background-color -> backgroundColor
              const camelKey = key.replace(/-([a-z])/g, (match, char) => char.toUpperCase());
              styleObj[camelKey] = value;
            }
            return styleObj;
          }, {});
        }
        // 其他属性直接保留,包括data-*自定义属性
        else {
          attributes[attrName] = attrValue;
        }
      }

      // 递归处理子节点,过滤空内容
      const children = Array.from(node.childNodes)
        .map(convertNode)
        .filter(child => child !== null);

      return React.createElement(tagName, attributes, ...children);
    }

    // 忽略注释等其他节点类型
    return null;
  };

  return convertNode(rootNode);
}

使用示例

function MyComponent({ htmlContent }) {
  return htmlStringToReactElement(htmlContent);
}

// 调用组件,直接渲染传入的锚点标签
<MyComponent htmlContent='<a href="/somepage" data-attr="something">Link here</a>' />

注意事项

  • XSS风险:和dangerouslySetInnerHTML一样,该方法会直接解析并渲染HTML内容,必须确保传入的HTML字符串完全可信,避免注入恶意代码。
  • 静态HTML限制:仅适配静态HTML内容,若HTML中包含脚本标签,DOMParser解析时不会执行脚本,但仍需谨慎处理不可信输入。
  • 特殊节点适配:对于SVG、自定义元素等特殊节点,可能需要额外添加适配逻辑来兼容React的渲染规则。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 22:08:22