You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

多子串匹配字符串问题:修复重复匹配时的内容重复生成问题

解决词汇多匹配位置重复生成的问题

我明白你的问题了——现在当一个词汇里有多个匹配输入文本的位置时,你的代码会把整个词汇重复生成多次,而不是在同一个词汇里把所有匹配的地方都高亮出来。咱们来拆解问题并给出解决方案:

问题根源

你的原代码中,对每个匹配项都会生成一个完整的带高亮的词汇版本,然后将这些版本都push到tmp数组,最后直接把tmp数组作为innerHTML渲染,这就导致了同一个词汇被重复显示多次,而不是在同一个词汇里高亮所有匹配位置。

解决方案

我们需要对每个词汇只构建一次包含所有高亮位置的字符串,而不是每个匹配都生成一次完整词汇。具体实现如下:

state.input !== '' && vocabularyItems && (
  vocabularyItems.map((vocabularyItem, index) => {
    const regex = new RegExp(input, 'gi');
    let resultStr = '';
    let lastIndex = 0;
    // 将匹配结果转换为数组,方便遍历处理
    const matches = [...vocabularyItem.matchAll(regex)];

    matches.forEach(match => {
      // 拼接当前匹配位置之前的普通文本
      resultStr += vocabularyItem.slice(lastIndex, match.index);
      // 保留原文本大小写,拼接高亮的匹配部分
      resultStr += `<strong className="tt-highlight">${match[0]}</strong>`;
      // 更新lastIndex到当前匹配的结束位置
      lastIndex = match.index + match[0].length;
    });

    // 拼接最后一个匹配之后剩余的文本
    resultStr += vocabularyItem.slice(lastIndex);

    return (
      <div 
        id={index} 
        className={`override-strong tt-suggestion tt-selectable ${cursor === index && 'tt-cursor'}`} 
        onMouseDown={handleClick} 
        key={index} 
        dangerouslySetInnerHTML={{ __html: resultStr }} 
      />
    );
  })
)

代码逻辑说明

  1. 获取所有匹配项:通过扩展运算符[...matchAll(regex)]将迭代器形式的匹配结果转为数组,方便后续遍历。
  2. 逐段拼接文本
    • lastIndex记录上一次处理到的字符串位置,初始值为0。
    • 遍历每个匹配项时,先拼接从lastIndex到当前匹配起始位置的普通文本。
    • 再将匹配到的原文本(保留原大小写)用高亮标签包裹后拼接。
    • 更新lastIndex到当前匹配的结束位置,确保下一段文本从正确的位置开始。
  3. 处理剩余文本:遍历完所有匹配项后,拼接最后一个匹配位置到字符串末尾的剩余文本。

这样修改后,同一个词汇内的所有匹配位置都会被正确高亮,且不会重复生成词汇。比如输入en时,Engagement会被渲染为:
<strong className="tt-highlight">En</strong>gagem<strong className="tt-highlight">en</strong>t

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

火山引擎 最新活动