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

如何在HTML格式的博客文章正文中嵌入React自定义组件

问题原因分析

你的原方案无法运行的核心原因有两点:

  • String.replace 是字符串处理方法,回调里返回的 JSX 是 React 元素对象,会被自动调用 toString() 转为 [object Object] 字符串,根本不会被解析为组件渲染
  • 原始 body 是 HTML 字符串,直接替换拆分后剩下的 HTML 片段没有经过 dangerouslySetInnerHTML 处理,会直接显示为纯文本,丢失原有格式

调整实现方案

你的整体思路是完全合理的:对存量文章侵入性极低、编辑成本低、扩展灵活。只需要调整处理逻辑,把字符串拆分后分别处理普通HTML段和占位符段,最后拼接为 React 元素数组即可:

import React from 'react';
import Slider from './Slider';
import Products from './Products';
import Gallery from './Gallery';

function ReplaceCodesWithComponents({ body }) {
  // 正则加括号,切割后会保留占位符在结果数组中
  const contentSegments = body.split(/(\[.+?\]\[\/\w+?\])/g);

  return contentSegments.map((segment, index) => {
    // 判断是否是占位符
    const placeholderMatch = segment.match(/^\[.+?\]\[\/(\w+?)\]$/);
    if (placeholderMatch) {
      const componentType = placeholderMatch[1];
      switch (componentType) {
        case "slider":
          return <Slider key={`comp-${index}`} />;
        case "products":
          return <Products key={`comp-${index}`} />;
        case "gallery":
          return <Gallery key={`comp-${index}`} />;
        default:
          // 匹配失败保留原内容,避免内容丢失
          return <span key={`raw-${index}`}>{segment}</span>;
      }
    }
    // 普通HTML片段用dangerouslySetInnerHTML渲染,all:unset避免容器破坏原有样式
    return (
      <div 
        key={`html-${index}`} 
        dangerouslySetInnerHTML={{ __html: segment }} 
        style={{ all: "unset" }} 
      />
    );
  });
}

使用时直接替换原有的 dangerouslySetInnerHTML 部分即可:

<ReplaceCodesWithComponents body={data.body} />

替换时机选择

不要在存入数据库时执行替换,建议在用户访问时由前端动态处理,原因如下:

  • 数据库存储原始的带占位符的HTML,后续修改占位符规则、迭代组件实现不需要批量修改历史存量数据,灵活性极高
  • 正则切割、渲染的性能开销极低,即使有数千篇文章也不会有明显性能问题
  • 原始内容直接可以用于编辑器回显,不需要额外做转义、转换处理,减少额外bug产生的可能

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.17 17:45:07