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

React中多词搜索时如何高亮段落中所有匹配词汇?

问题:实现搜索词拆分后的多词汇高亮展示

现有一个用于展示搜索结果的JSX元素,仅支持完全匹配搜索词的高亮。例如当searchTerm = 'hello world'且result.text = 'foo bar hello world it is hello'时,当前仅能高亮完整的"hello world",而无法单独高亮第二个"hello"。需要修改代码,实现将搜索词拆分为单个词汇后,所有匹配的词汇都被高亮,最终效果应为:foo bar <strong>hello world</strong> it is <strong>hello</strong>。

现有高亮相关代码如下:

// 展示高亮搜索结果的JSX
<div style={{ whiteSpace: 'normal' }}>
    {highlightMatch(documentationIndexState.searchTerm, result.text)}
</div>

// 高亮函数
function highlightMatch(searchTerm: string, text: string) {
    const parts = text.split(new RegExp(`(${searchTerm})`, 'gi'));
    return (
        <span>
            {' '}
            {parts.map((part, i) => (
                <span
                    key={i}
                    style={
                        part.toLowerCase() === searchTerm.toLowerCase() ? { fontWeight: 'bold', color: 'yellow' } : {}
                    }
                >
                    {part}
                </span>
            ))}{' '}
        </span>
    );
}

解决方案

要实现多词汇的独立高亮,需从以下几个方面修改代码:

  • 拆分搜索词为独立词汇:将输入的searchTerm按空白字符拆分,过滤掉空字符串(处理连续空格的情况)。
  • 转义正则特殊字符:对每个词汇进行正则转义,避免特殊字符(如+*?等)干扰正则匹配。
  • 构建多匹配正则:用|连接所有词汇,生成支持匹配任意单个词汇的正则表达式。
  • 修改高亮判断逻辑:不再判断是否与完整搜索词匹配,而是检查当前片段是否是拆分后的词汇之一(忽略大小写)。

修改后的完整代码如下:

// 展示高亮搜索结果的JSX(无需修改)
<div style={{ whiteSpace: 'normal' }}>
    {highlightMatch(documentationIndexState.searchTerm, result.text)}
</div>

// 修改后的高亮函数
function highlightMatch(searchTerm: string, text: string) {
    // 拆分搜索词为独立词汇,过滤空字符串,转义正则特殊字符
    const terms = searchTerm.split(/\s+/)
        .filter(term => term.trim() !== '')
        .map(term => term.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'));
    
    // 无有效搜索词时直接返回原文本
    if (terms.length === 0) {
        return <span>{text}</span>;
    }

    // 构建匹配任意词汇的正则,分组保留匹配内容,忽略大小写
    const regex = new RegExp(`(${terms.join('|')})`, 'gi');
    const parts = text.split(regex);

    // 生成高亮JSX
    return (
        <span>
            {parts.map((part, i) => {
                // 判断当前片段是否是搜索词汇之一(忽略大小写)
                const isMatch = terms.some(term => 
                    part.toLowerCase() === term.toLowerCase()
                );
                return (
                    <span
                        key={i}
                        style={isMatch ? { fontWeight: 'bold', color: 'yellow' } : {}}
                    >
                        {part}
                    </span>
                );
            })}
        </span>
    );
}

说明

  • 拆分搜索词时使用/\s+/正则,可以处理多个连续空格的情况。
  • 正则转义步骤确保了搜索词中的特殊字符(如hello?world)不会被当作正则语法解析。
  • 当搜索词为空或全是空格时,直接返回原文本,避免无效匹配。
  • 最终效果会同时高亮完整的"hello world"中的两个词汇,以及单独出现的"hello",符合需求。

内容的提问来源于stack exchange,提问作者xXx_emo_girl_xXx

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.07 06:25:21