如何在React中实现类Wiki自定义语法(禁用dangerouslySetInnerHTML)
嘿,你已经搞定了解析自定义标记这一步,真不错!接下来把这些解析结果转换成React组件数组其实没那么难,我给你捋捋具体怎么做~
首先核心思路是:把原始字符串拆分成「纯文本片段」和「标记片段」的有序数组,然后遍历这个数组,把每个片段转换成对应的React元素(文本节点或者自定义组件)。这样既能保留内容的顺序,又完全不用dangerouslySetInnerHTML,完美符合React的渲染逻辑。
第一步:把字符串拆分成有序的分段数组
假设你的自定义语法是[链接内容]代表链接,{粗体内容}代表粗体,我们可以用正则表达式把原始字符串拆分成包含文本和标记的片段数组:
function parseWikiContent(rawStr) { // 正则匹配[]或{}包裹的标记,()用来捕获匹配项,split会保留文本和标记 const markerRegex = /(\[.*?\]|\{.*?\})/g; const splitParts = rawStr.split(markerRegex); return splitParts.map(part => { if (part.startsWith('[') && part.endsWith(']')) { return { type: 'link', value: part.slice(1, -1) }; // 去掉[],拿到链接目标 } else if (part.startsWith('{') && part.endsWith('}')) { return { type: 'bold', value: part.slice(1, -1) }; // 去掉{},拿到粗体内容 } else { return { type: 'text', value: part }; // 普通文本片段 } }); }
第二步:把分段数组转换成React组件数组
有了有序的分段数组后,我们只需要遍历它,根据每个片段的type渲染对应的内容即可。这里假设你已经定义好了<Link>和<Bold>组件:
import React from 'react'; // 假设你的自定义组件已经实现 const Link = ({ where }) => ( <a href={`/wiki/${where.toLowerCase()}`} className="wiki-link"> {where} </a> ); const Bold = ({ string }) => <strong className="wiki-bold">{string}</strong>; // 负责转换的核心组件 function WikiRenderer({ content }) { const parsedSegments = parseWikiContent(content); return ( <div className="wiki-content"> {parsedSegments.map((segment, idx) => { // 注意:实际项目中如果有唯一标识,不要用index当key,这里只是示例 switch (segment.type) { case 'link': return <Link key={idx} where={segment.value} />; case 'bold': return <Bold key={idx} string={segment.value} />; case 'text': // React会自动把字符串转换成文本节点 return segment.value; default: return null; } })} </div> ); } // 使用示例 function App() { const demoText = "hello this is simple string [linkToSomewhere] {this is where bold goes}"; return <WikiRenderer content={demoText} />; } export default App;
关键点说明
- 顺序保留:用正则
split拆分字符串时,会严格保留原始内容的顺序,这样渲染出来的文本和组件位置才不会乱。 - 安全渲染:全程使用React组件和文本节点,完全避免了
dangerouslySetInnerHTML带来的XSS风险。 - 扩展性强:如果以后要加新的自定义标记(比如
*斜体*或者#标题#),只需要在parseWikiContent里加对应的正则判断,然后在switch里加新的组件分支就行。
如果你的解析逻辑已经能拿到单独的link和bold数组,只需要调整一下拆分字符串的逻辑,保证最终生成的分段数组是有序的就行~
内容的提问来源于stack exchange,提问作者김성민
相关产品推荐
相关产品推荐

