React实现文字高亮

在React项目开发中,需要实现搜索后高亮显示关键词,特别是当文本包含表情图片和代码块等HTML元素时。通过抽取HTML标签并重新生成高亮字符串,结合`dangerouslySetInnerHTML`解析,成功解决了这个问题。文中还提到了原有实现的bug及改良后的解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在项目开发中遇到一个头疼的问题,就是在搜索数据后渲染的同时把框出来的部分命中搜索关键词经行高亮,如果是普通的字符串高亮很简单,调用_match方法就行了当然,可以直接返回jsx(代码中被注释的部分),但是如图,不是纯文本,里面掺杂中表情的img标签,也有可能是提交的代码块,比如:

dal;jksdajk[闭嘴][闭嘴][大哭][再见][亲亲][示爱][哈欠]dajalkjg <img src=“eeee.png” alt=“图片” />@cp1 @cp2

其中img标签是不允许被破坏的,所以就需要对文本进行抽取其中的html标签部分后在重新生成新的高亮后的字符串或jsx,在react中通过 dangerouslySetInnerHTML经行解析,最终实现效果如下图

在这里插入图片描述

  const _match = (keyword, content) => {
    const reg = new RegExp(keyword.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&'), 'ig')

    const splitIconTypes = content.split(reg)
    const match = content.match(reg)
    let matchStr = (match || [])
      .map((_, index) => {
        return `${splitIconTypes[index]}<span class="highlight">${match[index]}</span>`
      })
      .join('')
    return `${matchStr}<span&
<think>嗯,用户问的是在React中如何实现文字高亮。首先,我需要考虑几种常见的方法。可能的方法包括字符串替换、使用dangerouslySetInnerHTML,或者利用第三方库。不过得先分析每种方法的优缺点,以及适用场景。 首先,字符串替换的方法,应该是最直接的。比如把目标关键词用<mark>标签包裹起来。但这里需要注意大小写是否敏感,是否需要全词匹配,以及性能问题。特别是当文本很大或者需要多次替换时,可能会影响性能。另外,使用split和map的方式可能比较高效,可以避免正则表达式的性能问题。 然后,使用dangerouslySetInnerHTML的方法,虽然可以方便地插入HTML,但存在XSS攻击的风险。必须确保内容来源可信,否则会有安全隐患。所以需要提醒用户注意这一点,不建议在无法控制内容的情况下使用。 接下来,第三方库如highlight.js可能会有更多的功能,比如支持多种语言高亮,或者更复杂的匹配规则。但引入库会增加包的大小,可能对于简单需求来说不太划算。需要根据项目需求来决定是否使用。 另外,用户可能需要高亮多个不同的关键词,或者动态改变高亮词。这时候需要更灵活的处理方式,比如将关键词作为数组传入,循环处理替换。或者支持正则表达式,比如用RegExp来动态创建匹配模式,但要注意转义特殊字符,避免正则出错。 还有样式方面,虽然<mark>标签有默认样式,但用户可能想自定义高亮颜色或者其他样式。这时候需要指导用户如何通过CSS或者内联样式来修改,比如在<mark>标签中添加类名或者style属性。 另外,可能要考虑性能优化。比如在长文本中频繁替换大量关键词,是否会导致渲染延迟。这时候可能需要分块处理,或者使用虚拟滚动等技术,但可能超出了当前问题的范围,但可以作为进阶建议提及。 还有交互方面的需求,比如点击高亮词触发事件。这时候需要在生成元素时添加事件处理函数,但要注意在React中动态绑定事件可能需要使用useCallback或者避免在渲染中直接定义函数,以防止不必要的重新渲染。 最后,总结几种方法的适用场景,帮助用户根据具体需求选择最合适的方案。比如简单的高亮用字符串替换,安全的内容用dangerouslySetInnerHTML,复杂需求用第三方库。同时提醒安全性和性能问题。</think>在 React实现文字高亮主要有以下几种方案,按实现难度和场景需求逐步说明: --- ### 方案 1:字符串替换法(基础版) **适用场景**:简单关键词高亮 ```jsx const HighlightText = ({ text, keyword }) => { const parts = text.split(new RegExp(`(${keyword})`, 'gi')); return ( <span> {parts.map((part, i) => part.toLowerCase() === keyword.toLowerCase() ? <mark key={i}>{part}</mark> : part )} </span> ); }; // 使用 <HighlightText text="Hello React World" keyword="React" /> ``` --- ### 方案 2:多关键词 & 安全渲染 **适用场景**:需要防XSS攻击时 ```jsx const SafeHighlight = ({ text, keywords }) => { const regex = new RegExp(`(${keywords.join('|')})`, 'gi'); const parts = text.split(regex); return ( <div dangerouslySetInnerHTML={{ __html: parts.map(part => keywords.some(kw => kw.toLowerCase() === part.toLowerCase()) ? `<mark>${part}</mark>` : part ).join('') }} /> ); }; // 使用(需自行处理关键词转义) <SafeHighlight text="User input content" keywords={['danger', 'alert']} /> ``` --- ### 方案 3:复杂高亮组件 **适用场景**:需要支持正则表达式、样式定制 ```jsx const AdvancedHighlighter = ({ text, pattern, highlightStyle }) => { const matches = text.match(pattern) || []; const chunks = text.split(pattern); return ( <div> {chunks.map((chunk, index) => ( <span key={index}> {chunk} {matches[index] && <mark style={highlightStyle}>{matches[index]}</mark>} </span> ))} </div> ); }; // 使用 <AdvancedHighlighter text="Error: 404 Not Found" pattern={/\b\d{3}\b/g} highlightStyle={{ backgroundColor: '#ffeb3b' }} /> ``` --- ### 方案 4:使用第三方库 推荐库:`react-highlight-words` ```bash npm install react-highlight-words ``` ```jsx import Highlighter from 'react-highlight-words'; <Highlighter highlightClassName="custom-highlight" searchWords={['important', 'warning']} autoEscape={true} textToHighlight="This is an important warning message" /> ``` --- #### 关键注意事项: 1. **性能优化**:长文本建议使用虚拟滚动(如`react-window`) 2. **大小写敏感**:通过`toLowerCase()`统一处理 3. **特殊字符转义**:使用`escape-string-regexp`处理关键词中的正则符号 4. **样式控制**:通过CSS定义`mark`标签或自定义类名 5. **服务端渲染**:需兼容SSR场景时避免直接操作DOM 根据具体需求选择方案,简单场景推荐方案1,生产环境推荐方案4+自定义扩展。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值