如何在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
相关产品推荐
相关产品推荐

