如何使用包含JSX代码的内容替换字符串中的指定文本?
实现思路
String.replace只能处理字符串类型的替换值,无法直接插入JSX对象,你可以通过分割字符串为混合文本+JSX的片段数组的方式实现需求,核心逻辑是把内容中匹配到的空白词替换为对应的span组件,其余部分保留为普通文本节点。
具体实现步骤
- 先写正则特殊字符转义工具:避免空白词包含正则元字符(如
.,*)时匹配逻辑异常 - 对每张卡片的内容,通过正则捕获所有需要替换的空白词,将字符串分割为「普通文本/空白词」交替的片段数组
- 遍历片段数组,匹配到空白词时返回带样式和点击事件的span组件,其余片段直接返回文本即可
- 支持同一空白词多次出现、多空白词混合的场景
完整代码示例
import React from 'react'; interface ICard { content: string; blanks: Array<{ word: string; hidden: boolean }>; } // 转义正则特殊字符 const escapeRegExp = (str: string) => { return str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); }; function processCards(cards: ICard[] | null): Array<React.ReactNode> { if (!cards) return []; return cards.map((card, cardIndex) => { // 构造包含所有空白词的正则,用括号捕获匹配项,split后会保留匹配到的词 const allWords = card.blanks.map(b => escapeRegExp(b.word)); const matchReg = new RegExp(`(${allWords.join('|')})`, 'g'); const fragments = card.content.split(matchReg); // 构造word到blank配置的映射,方便快速查找 const wordMap = new Map( card.blanks.map((blank, index) => [blank.word, { ...blank, index }]) ); // 遍历片段生成最终内容 return fragments.map((fragment, idx) => { const matchedBlank = wordMap.get(fragment); if (matchedBlank) { const visibility = matchedBlank.hidden ? 'hidden' : 'visible'; return ( <span key={`blank-${cardIndex}-${matchedBlank.index}-${idx}`} className={visibility} onClick={() => toggleBlank(cardIndex, matchedBlank.index)} > {fragment} </span> ); } return <React.Fragment key={`text-${cardIndex}-${idx}`}>{fragment}</React.Fragment>; }); }); } // 你的toggleBlank函数按原有逻辑实现即可 const toggleBlank = (cardIndex: number, blankIndex: number) => { // 原有状态更新逻辑 };
注意事项
- 如果存在多个空白词完全相同的场景,可以在拆分时记录当前匹配的位置,对应到正确的blankIndex即可,上述实现默认一个word只对应一个blank配置,有重复词需求时可自行调整映射逻辑
- 所有返回的片段都需要添加唯一key,避免React渲染警告
- 最终返回的数组元素是React节点,可以直接在JSX中渲染使用
内容的提问来源于stack exchange,提问作者Raven
相关产品推荐
相关产品推荐

