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

如何在JSON数据中嵌入HTML/CSS标签并在React动态组件中渲染

如何在JSON数据中嵌入HTML/CSS标签并在React动态组件中渲染

当然可以实现啦!我来给你两种实用的方案,结合你的代码场景一步步说明:

方案1:用dangerouslySetInnerHTML渲染HTML字符串

如果你的JSON内容是自己维护的静态HTML(无用户输入风险),这个方法最直接:

步骤1:修改JSON内容,加入HTML标签

把content字段改成带HTML和class的字符串,比如:

[
    {
        "header": "Desserts",
        "src": "",
        "cover": true
    },
    {
        "header": "Fl-Earl Gray Cake",
        "content": "<h3 class='recipe-header'>制作要点</h3><p>Earl gray and marzipan-chunks sponge cake (1:1:1 b:s:f ratio, 3 eggs) soaked with çiçek suyu and rose syrup.</p><p><em>Rose cream cheese frosting.</em></p>",
        "link": "https://theclovecoterie.substack.com/p/nosferatu-cake",
        "src": "/kitchen/cake.jpg",
        "cover": false
    }
]

步骤2:在React组件中用dangerouslySetInnerHTML渲染

修改你map里的Page组件渲染逻辑,把{element[1].content}替换成带该属性的容器:

export default function RecipeBook() {
  const searchParams = useSearchParams();
  const book = useRef();
  const [pages, setPages] = useState([]);

  useEffect(() => {
    const recipeElems = Object.entries(recipes).map((element, i) => {
      if (element[1].cover) {
        return <PageCover key={i} side={i%2===0 ? "L" : "R"}> {element[1].header} </PageCover>
      } else if (element[1].link !== "") {
        return (
          <Page key={i} src={element[1].src} side={i%2===0 ? "L" : "R"} header={element[1].header}> 
            {/* 用dangerouslySetInnerHTML渲染HTML字符串 */}
            <div dangerouslySetInnerHTML={{ __html: element[1].content }} />
            Inspired by this <a href={element[1].link}>recipe.</a> 
          </Page> 
        )
      } else {
        return (
          <Page key={i} src={element[1].src} side={i%2===0 ? "L" : "R"} header={element[1].header}> 
            <div dangerouslySetInnerHTML={{ __html: element[1].content }} />
          </Page> 
        )
      }
    });
    setPages(recipeElems);
  }, [])  

  return (
    <div className="bookContainer">
      <HTMLFlipBook
        className="book"
        ref={book}
        width={350} height={450}
        maxWidth={350} maxHeight={450}
        size="stretch"
        maxShadowOpacity={0}
      >
        {pages}
      </HTMLFlipBook>
    </div>
  );
}

⚠️ 注意:这个方法名字里的dangerously是提醒你——如果HTML内容来自不可信的用户输入,会有XSS攻击风险。但如果是你自己写的静态内容,完全可以放心用。

方案2:改用JS模块存储JSX内容(更安全更React化)

如果你想使用React的完整特性(比如CSS Modules、自定义组件),或者担心安全问题,可以把JSON改成JS模块:

步骤1:创建recipes.js模块

把原来的JSON数组改成JSX支持的结构,直接写React元素:

// 假设你有自定义样式文件,可以导入使用
import styles from './RecipeStyles.module.css';

export default [
    {
        "header": "Desserts",
        "src": "",
        "cover": true
    },
    {
        "header": "Fl-Earl Gray Cake",
        "content": (
            <>
                <h3 className={styles.recipeHeader}>制作要点</h3>
                <p>Earl gray and marzipan-chunks sponge cake (1:1:1 b:s:f ratio, 3 eggs) soaked with çiçek suyu and rose syrup.</p>
                <p><em>Rose cream cheese frosting.</em></p>
                <p>Rose marmalade to decorate.</p>
            </>
        ),
        "link": "https://theclovecoterie.substack.com/p/nosferatu-cake",
        "src": "/kitchen/cake.jpg",
        "cover": false
    }
];

步骤2:在组件中直接渲染JSX

导入这个JS模块后,直接把content当作React元素渲染即可:

// 导入JS模块而非JSON
import recipes from './recipes.js';

export default function RecipeBook() {
  // ...其他逻辑不变
  useEffect(() => {
    const recipeElems = Object.entries(recipes).map((element, i) => {
      if (element[1].cover) {
        return <PageCover key={i} side={i%2===0 ? "L" : "R"}> {element[1].header} </PageCover>
      } else if (element[1].link !== "") {
        return (
          <Page key={i} src={element[1].src} side={i%2===0 ? "L" : "R"} header={element[1].header}> 
            {/* 直接渲染JSX内容 */}
            {element[1].content}
            Inspired by this <a href={element[1].link}>recipe.</a> 
          </Page> 
        )
      } else {
        return (
          <Page key={i} src={element[1].src} side={i%2===0 ? "L" : "R"} header={element[1].header}> 
            {element[1].content}
          </Page> 
        )
      }
    });
    setPages(recipeElems);
  }, [])  
  // ...返回部分不变
}

这个方案的好处是完全兼容React生态,能使用组件、样式模块,而且没有XSS风险——React会自动处理内容的安全性。

备注:内容来源于stack exchange,提问作者user

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.14 13:48:07