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

JavaScript实现关键词匹配片段用<em>包裹 无匹配时隐藏条目

多关键词部分匹配高亮实现方案

问题场景

现有搜索输入框支持用户输入空格分隔的关键词,在条目列表中执行搜索,要求:

  • 仅展示匹配任意关键词的条目
  • 高亮条目中命中搜索词的片段

已知输入

待搜索条目数组:

const haystacks = [
 { value: 'Hello World', visible: true }, 
 { value: 'I was here', visible: true }, 
 { value: 'tell me your name', visible: true }
];

搜索关键词数组:

const needles = ['el', 'rl', 'em'];

预期输出

[
  { value: 'H<em>el</em>lo Wo<em>rl</em>d', visible: true }, 
  { value: 'I was here', visible: false }, 
  { value: 't<em>el</em>l me your name', visible: true }
]

原有代码问题

原有实现存在两个核心错误:

  • 标签嵌套错乱:逐关键词循环时,直接修改条目value值后再做下一轮匹配,后续关键词会把已插入的<em>标签中的em字符当成普通文本匹配,生成错乱的嵌套标签。
  • 可见性判断错误:逐关键词循环时直接把当前关键词的匹配结果赋值给visible属性,后续未匹配的关键词会覆盖之前命中设置的true值,导致可见性判断不准。

原有错误代码:

const haystacks = [{ value: 'Hello World', visible: true }, { value: 'I was here', visible: true }, { value: 'tell them your name', visible: true }];

const needles = ['el', 'rl', 'em'];

for (const haystack of haystacks) {
  for (const needle of needles) {
    const isMatchingOption = haystack.value.toLowerCase().includes(needle);
    haystack.visible = isMatchingOption;
    if (isMatchingOption) {
      const re = new RegExp(needle.replace(/([.?*+^$[\]\\(){}|-])/g, '\\$1'), 'gi');
      haystack.value = haystack.value.replace(re, '<em>$&</em>');
    }
  }
}

console.log(haystacks);

修正后实现

核心思路:所有匹配、替换操作都基于条目原始纯文本值执行,避免匹配到插入的标签字符;合并所有关键词生成单个全局匹配正则,一次性完成匹配判断和高亮替换,避免逐次修改值带来的问题。

const haystacks = [{ value: 'Hello World', visible: true }, { value: 'I was here', visible: true }, { value: 'tell me your name', visible: true }];
const needles = ['el', 'rl', 'em'];

// 转义关键词中的正则特殊字符,合并生成全局不区分大小写的匹配正则
const escapedNeedles = needles.map(needle => needle.replace(/([.?*+^$[\]\\(){}|-])/g, '\\$1'));
const keywordReg = new RegExp(`(${escapedNeedles.join('|')})`, 'gi');

for (const item of haystacks) {
  const originalText = item.value;
  // 基于原始文本判断是否命中任意关键词
  const isMatched = keywordReg.test(originalText);
  item.visible = isMatched;
  if (isMatched) {
    // 基于原始文本一次性完成所有关键词的高亮包裹
    item.value = originalText.replace(keywordReg, '<em>$1</em>');
  }
}

console.log(haystacks);

运行上述代码即可得到符合预期的输出,无标签嵌套问题,可见性判断准确。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 22:45:47