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

动态注入含HTML文本的自定义组件失败:替换<abbr>后无法渲染求解

动态注入React自定义组件到HTML文本的解决方案

问题背景

需要将包含HTML的文本中的<abbr title=""></abbr>标签替换为自定义CustomComponent并使其渲染生效,但现有代码仅在DOM中生成了customcomponent标签,组件并未实际渲染。

现有代码

原始HTML文本:

<h1>Lorem</h1> ipsum <abbr title="">Test1</abbr> dolor sit amet <abbr title="">Test2</abbr> lorem ipsum <abbr title="">Test3</abbr>.

替换函数:

let injectComponent = (text) => {
    let replacedText;

    const regex = /\&lt;abbr title=&quot;&quot;&gt;(.*?)\&lt;\/abbr&gt;/g;

    replacedText = text.replace(regex,function(_,match) {
        return  `&lt;CustomComponent data=&quot;${match}&quot; /&gt;`
    })
    
    return replacedText;
}

使用方式:

<span className="text-slate-900"
    dangerouslySetInnerHTML={{ __html: injectComponent(post.content) }}>
</span>

问题原因

dangerouslySetInnerHTML的作用是将字符串解析为普通DOM元素,无法识别React组件标签。它只会把<CustomComponent>当作普通HTML标签处理,不会触发React的组件渲染流程,因此组件不会生效。

解决方案

方案一:使用react-html-parser库解析并转换

该库可以将HTML字符串转换为React元素,并支持自定义标签转换规则。

  1. 安装依赖:
npm install react-html-parser
  1. 修改代码实现:
import ReactHtmlParser, { convertNodeToElement } from 'react-html-parser';
import CustomComponent from './CustomComponent'; // 引入你的自定义组件

const injectComponent = (text) => {
  return ReactHtmlParser(text, {
    transform: (node) => {
      // 匹配目标abbr标签
      if (node.type === 'tag' && node.name === 'abbr' && node.attribs.title === '') {
        // 提取标签内的文本内容
        const content = node.children?.[0]?.data || '';
        // 返回自定义组件
        return <CustomComponent data={content} />;
      }
      // 其他标签按默认逻辑转换为React元素
      return convertNodeToElement(node, {}, React);
    }
  });
};

// 使用时直接渲染转换后的结果
return <span className="text-slate-900">{injectComponent(post.content)}</span>;

方案二:手动拆分文本与组件(无第三方依赖)

通过正则拆分原始文本,区分普通HTML文本和需要替换的<abbr>内容,分别处理后生成React元素数组。

import CustomComponent from './CustomComponent';

const injectComponent = (text) => {
  // 匹配所有目标abbr标签
  const abbrRegex = /<abbr title="">(.*?)<\/abbr>/g;
  // 将文本拆分为普通HTML段和abbr内容段交替的数组
  const parts = text.split(abbrRegex);

  return parts.map((part, index) => {
    // 奇数索引对应abbr标签内的内容,渲染自定义组件
    if (index % 2 === 1) {
      return <CustomComponent key={index} data={part} />;
    }
    // 偶数索引是普通HTML文本,用dangerouslySetInnerHTML解析
    return (
      <span key={index} dangerouslySetInnerHTML={{ __html: part }} />
    );
  });
};

// 使用方式
return <span className="text-slate-900">{injectComponent(post.content)}</span>;

注意事项

  • 如果文本包含用户输入的内容,务必做好XSS防护,避免恶意代码注入。
  • 方案一的第三方库能更好地处理复杂HTML结构(如嵌套标签),方案二更适合简单场景且无需额外依赖。

内容的提问来源于stack exchange,提问作者Jérémie Chazelle

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 07:04:54