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

如何实现基于searchString的标题<mark>高亮JSX生成函数?

解决React中高亮匹配字符串并返回可渲染JSX的问题

我来帮你搞定这个问题——你当前的代码返回的是带<mark>标签的字符串,React会把它当成普通文本渲染,而不是解析成实际的高亮标签。要实现真正的高亮效果,我们需要生成JSX元素数组,而不是纯字符串。

问题分析

你的原代码用string.replace返回的是字符串形式的<mark>Banana</mark>,React只会把这段内容当成文本输出,不会渲染成<mark>元素。我们需要把标题拆分成「匹配搜索词的片段」和「不匹配的片段」,然后分别把匹配的片段用<mark>包裹,最后组装成JSX数组。

完整解决方案代码

const markString = (title, searchString) => {
  // 处理空搜索字符串的情况,直接返回原标题
  if (!searchString.trim()) {
    return <span>{title}</span>;
  }

  // 转义正则表达式中的特殊字符(比如.、*、?等),避免搜索时出现意外匹配
  const escapedSearchString = searchString.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
  // 创建不区分大小写、全局匹配的正则,用分组来保留匹配的片段
  const regex = new RegExp(`(${escapedSearchString})`, 'gi');

  // 将标题分割为「匹配片段」和「非匹配片段」的数组
  const parts = title.split(regex);

  // 遍历片段数组,组装成JSX元素
  return parts.map((part, index) => {
    // 判断当前片段是否匹配搜索词(不区分大小写)
    if (part.toLowerCase() === searchString.toLowerCase()) {
      return <mark key={index}>{part}</mark>;
    }
    // 过滤掉分割产生的空字符串,避免渲染无用元素
    if (part === '') {
      return null;
    }
    return <span key={index}>{part}</span>;
  });
};

场景测试

当searchString为"ab"、title为"abracadabra"时,这个函数会返回以下JSX数组:

[
  <mark>ab</mark>,
  'racad',
  <mark>ab</mark>,
  'ra'
]

React会自动将这个数组渲染成你期望的效果:<mark>ab</mark>racad<mark>ab</mark>ra。

关键细节说明

  • 正则特殊字符转义:如果用户搜索的是类似"a.b"这样的内容,不转义的话正则会匹配"a任意字符b",转义后才能精确匹配"a.b"。
  • 全局匹配(g修饰符):确保标题中所有匹配搜索词的部分都被高亮,而不只是第一个。
  • key属性:React要求列表中的每个元素都有唯一的key,这里用数组索引是安全的,因为片段的顺序不会改变。
  • 空片段过滤:用正则分组分割时,可能会产生空字符串,需要过滤掉避免渲染空的DOM元素。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.12 04:41:36