HOW - 如何实现搜索结果关键词高亮展示

news2024/10/23 12:48:41

目录

  • 方案 1:后端返回带有标记的文本
  • 方案 2:前端处理高亮显示(后端只返回纯文本)
  • 方案 3:后端返回匹配位置,前端负责高亮
  • 方案选择的考量:

在前端实现关键词检索后的高亮展示以及前后端接口设计时,通常有几种可选方案。以下是一些推荐的实现方案,分别涵盖了前后端设计和前端的高亮展示:

方案 1:后端返回带有标记的文本

  1. 后端接口设计

    • 在后端处理搜索逻辑时,直接将匹配到的 keyword 用特定标记(例如 <mark> 标签或自定义标记符号)包裹,返回的数据中包含带有标记的 titledescription
    • 返回的数据结构可能类似这样:
      [
        {
          "title": "This is a <mark>keyword</mark> example",
          "description": "Find the <mark>keyword</mark> in this description"
        }
      ]
      
  2. 前端渲染

    • 前端可以直接使用 dangerouslySetInnerHTML 渲染后端返回的标记内容,来展示高亮效果。
    const renderTextWithHighlight = (text: string) => {
      return <span dangerouslySetInnerHTML={{ __html: text }} />;
    };
    
    const SearchResults = ({ results }) => {
      return results.map(item => (
        <div key={item.title}>
          <h3>{renderTextWithHighlight(item.title)}</h3>
          <p>{renderTextWithHighlight(item.description)}</p>
        </div>
      ));
    };
    

方案 2:前端处理高亮显示(后端只返回纯文本)

  1. 后端接口设计

    • 后端只返回普通的 titledescription 字段,不带任何高亮标记。返回结构例如:
      [
        {
          "title": "This is a keyword example",
          "description": "Find the keyword in this description"
        }
      ]
      
  2. 前端渲染

    • 前端接收数据后,自己在渲染时根据 keyword 进行字符串匹配,并使用 React 组件去动态生成包含高亮的文本片段。
    • 可以通过 split 方法分割匹配到的 keyword,然后用 <span> 包裹高亮的部分。例如:
    const highlightText = (text: string, keyword: string) => {
      const parts = text.split(new RegExp(`(${keyword})`, 'gi'));
      return (
        <span>
          {parts.map((part, i) =>
            part.toLowerCase() === keyword.toLowerCase() ? (
              <span key={i} style={{ color: 'red' }}>{part}</span>
            ) : (
              part
            )
          )}
        </span>
      );
    };
    
    const SearchResults = ({ results, keyword }) => {
      return results.map(item => (
        <div key={item.title}>
          <h3>{highlightText(item.title, keyword)}</h3>
          <p>{highlightText(item.description, keyword)}</p>
        </div>
      ));
    };
    

方案 3:后端返回匹配位置,前端负责高亮

  1. 后端接口设计

    • 后端除了返回 titledescription 外,还返回每个字段中匹配的 keyword 的位置,方便前端处理高亮。返回结构例如:
      [
        {
          "title": "This is a keyword example",
          "description": "Find the keyword in this description",
          "matches": {
            "title": [10, 17],
            "description": [9, 16]
          }
        }
      ]
      
  2. 前端渲染

    • 前端根据后端返回的匹配位置来生成高亮的文本片段,使用 substring 方法或者字符分割的方式在指定位置应用高亮:
    const highlightTextByPositions = (text: string, positions: number[]) => {
      const parts = [];
      let lastIndex = 0;
      for (let i = 0; i < positions.length; i += 2) {
        const start = positions[i];
        const end = positions[i + 1];
        parts.push(text.substring(lastIndex, start));
        parts.push(<span style={{ color: 'red' }}>{text.substring(start, end)}</span>);
        lastIndex = end;
      }
      parts.push(text.substring(lastIndex));
      return <span>{parts}</span>;
    };
    
    const SearchResults = ({ results }) => {
      return results.map(item => (
        <div key={item.title}>
          <h3>{highlightTextByPositions(item.title, item.matches.title)}</h3>
          <p>{highlightTextByPositions(item.description, item.matches.description)}</p>
        </div>
      ));
    };
    

方案选择的考量:

  • 方案 1(后端处理高亮):这种方式后端负担较大,前端只负责渲染标记好的内容。适合对 SEO 或者后端内容展示有特殊要求的情况,但需要注意 dangerouslySetInnerHTML 的使用安全性。
  • 方案 2(前端处理高亮):前端处理高亮逻辑更加灵活,后端无需改动。适合前端性能需求较高但内容不会太大的场景。
  • 方案 3(后端返回匹配位置,前端高亮):这种方式前后端工作相对均衡,但需要增加后端逻辑去精确返回匹配的位置。

根据你的需求,前后端的技术栈、性能要求,以及团队协作分工,可以在这些方案中选择最适合的一种。如果搜索结果较多或复杂,可以考虑后端返回带有标记或匹配位置的信息,减少前端计算的复杂度。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2221584.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

双十一期间有哪些入手不亏的数码好物?这五款优质产品不容错过!

在这个令人期待的双十一购物狂欢节期间&#xff0c;我们总希望能以最实惠的方式&#xff0c;入手那些能够提升生活品质的数码好物。但是还有一些人还在犹豫考虑&#xff0c;不知道入手什么产品比较好&#xff0c;我也是特地挑选了五款实用又富有创意的数码产品&#xff0c;希望…

通过AI检测越权漏洞的指令

通过AI检测越权漏洞的指令 这段指令描述了一个AI的功能和工作流程&#xff0c;主要是用于比较两个HTTP响应数据包&#xff0c;以检测潜在的越权行为。以下是对其内容的详细介绍&#xff1a; 效果 先看一个简单的示例效果&#xff1a; 指令详情 指令详情&#xff1a; {&q…

快速上手C语言【下】(非常详细!!!)

目录 1. 指针 1.1 指针是什么 1.2 指针类型 1.2.1 指针-整数 1.2.2 指针解引用 1.3 const修饰 1.4 字符指针 1.5 指针-指针 1.6 二级指针 2. 数组 2.1 定义和初始化 2.2 下标引用操作符[ ] 2.3 二维数组 2.4 终极测试 3. 函数 3.1 声明和定义 3.2 传值调用…

Java最全面试题->Java基础面试题->JavaEE面试题->Web应用服务器面试题

文章目录 Web应用服务器面试题Tomcat是什么?Tomcat缺省端口是多少&#xff0c;如何修改&#xff1f;Tomcat 有那几种Connector 运行模式&#xff1f;什么是Servlet&#xff1f;Servlet请求过程&#xff1f;Tomcat执行流程&#xff1f;Tomcat部署方式?什么是JBoss ?在JBoss 7…

数据结构与算法:贪心算法与应用场景

目录 11.1 贪心算法的原理 11.2 经典贪心问题 11.3 贪心算法在图中的应用 11.4 贪心算法的优化与扩展 总结 数据结构与算法&#xff1a;贪心算法与应用场景 贪心算法是一种通过选择当前最佳解来构造整体最优解的算法策略。贪心算法在很多实际问题中都取得了良好的效果&am…

双十一母婴必买清单 推荐超实用母婴用品

随着双十一购物狂欢节的临近&#xff0c;无数准父母和年轻家长开始摩拳擦掌&#xff0c;准备为家中的小宝贝抢购一系列高品质、实用的母婴用品。在这个年度最大的电商促销活动中&#xff0c;选择对的产品不仅能够节省开支&#xff0c;更能确保宝宝的健康成长与舒适生活。以下是…

告别微信封号!学会这5招,让你的账号坚不可摧

在这个信息爆炸的时代&#xff0c;无论是工作沟通、社交互动还是获取信息&#xff0c;微信都扮演着极其重要的角色。但是&#xff0c;随着微信平台规则的日益严格&#xff0c;账号被封的风险也随之增加。今天&#xff0c;我们就来聊聊如何有效防止 微信被封&#xff0c;让你的账…

Java基于SSM微信小程序物流仓库管理系统设计与实现(源码+lw+数据库+讲解等)

选题背景 随着社会的发展&#xff0c;社会的方方面面都在利用信息化时代的优势。互联网的优势和普及使得各种系统的开发成为必需。 本文以实际运用为开发背景&#xff0c;运用软件工程原理和开发方法&#xff0c;它主要是采用java语言技术和mysql数据库来完成对系统的设计。整个…

搞错了,再来!谷歌利用AI重新推出全新的Google Shopping

近年来&#xff0c;随着电子商务的迅猛发展&#xff0c;消费者对个性化和便捷购物体验的需求愈发高涨。谷歌&#xff0c;作为互联网巨头之一&#xff0c;一直在不断探索和创新&#xff0c;它一直在应对这样一个事实&#xff1a;越来越多的消费者首先访问零售商的网站&#xff0…

jmeter正则表达式教程

正则表达式用于提取相应数据中的代码、文本等数据&#xff0c;利用正则表达式&#xff0c;提取响应数据&#xff0c;移植到下一线程组的参数中&#xff0c;从而进行测试。 一、解释&#xff1a;解释很多&#xff0c;但是最关键 &#xff08;1&#xff09;注释不多说&#xff0c…

实验干货|电流型霍尔传感调理电路设计01

在做逆变器实验时&#xff0c;需要测量逆变器输出电压以及电流。作为初学者&#xff0c;因为缺乏经验也踩过不少坑&#xff0c;写一篇博客记录下来希望能帮到跟我一样的初学者。 踩坑回顾 用什么采样&#xff1f;片内ADC还是片外ADC&#xff1f; 早前&#xff0c;在用RTLAB做…

51单片机快速入门之 LCD1602 液晶显示屏2024/10/19

51单片机快速入门之 LCD1602 液晶显示屏 Proteus 电路图 : 74HC595 拓展电路可以不用,给 p0-p17 添加上拉电阻也可以!,我这里是方便读取和节省电阻线路 (因为之前不知道 在没有明确循环的情况下&#xff0c;Keil编译器可能会在main()中自动添加类似以下的汇编代码&#xff1a…

手机淘宝自动下单退货自动化RPA脚本机器人

使用手机集线器连接多个手机并发运行。 脚本分3个部分&#xff08;读取本地连接下单&#xff0c;退货获取退货地址信息&#xff0c;填写快递单号&#xff09; 脚本部分图结构看下面的图片 部分数据统计展示

ORACLE SELECT INTO 赋值为空,抛出 NO DATA FOUND 异常

例子&#xff1a; DECLARE ORDER_NUM VARCHAR2(20); BEGIN SELECT S.ORDER_NUM INTO ORDER_NUM FROM SALES_ORDER S WHERE S.ID122344; DBMS_OUTPUT.PUT_LINE(单号: || ORDER_NUM); END; 在查询结果为空的情况下&#xff0c;以上代码会报错&#xff1a;未找到任何数据 解决方…

1024程序员节探讨<程序员的人生观和价值观>

程序员的人生观和价值观 程序员的人生观和价值观往往受到其职业特性和工作环境的影响&#xff0c;但也会因个体差异而有所不同。 人生观 持续学习与成长&#xff1a; 程序员通常认识到技术的快速发展&#xff0c;因此他们倾向于保持一种持续学习和自我提升的态度。他们可能将…

全网最详细图文测评!Stability.AI 发布 SD3.5 Large 模型,能否逆风翻盘超越FLUX?

原文链接&#xff1a;全网最详细图文测评&#xff01;Stability.AI 发布 SD3.5 Large 模型&#xff0c;能否逆风翻盘超越FLUX&#xff1f; (chinaz.com) SD3.5 的前世今生 6 月的时候&#xff0c;Stability AI发布了 Stable Diffusion 3 Medium&#xff0c;但是在在 FLUX 发布…

FPGA学习(7)-线性序列机原理与应用,不同类型的LED控制开关

目录 1.实现1 2.实现2 2.1方法1 2.2方法2 3.实现3 3.1实验现象 4.实现4 4.1分析 4.2实现过程 4.2.1 counter的计数 4.2.2 en_counter2的判断 4.2.3 en_counter0的判断 4.2.4 对case语句加判断条件 4.3仿真结果 ​编辑 4.4实验现象 1.实现1 1.实现以下图示功能…

qt QBuffer详解

QBuffer 是 Qt 提供的一个类&#xff0c;用于在内存中操作二进制数据。它是 QIODevice 的一个子类&#xff0c;允许你将数据读入和写出到一个内存缓冲区&#xff0c;而不需要与文件系统交互。 常用方法 构造函数: QBuffer(QObject *parent nullptr): 创建一个空的 QBuffer 对象…

vue项目启动报错:exit status 1

vue项目启动报错&#xff1a;&#xff08;vite构建&#xff09; npm ERR! code ELIFECYCLE npm ERR! errno 1 npm ERR! Exit status 1 如下图所示&#xff1a; 解决 检查node版本&#xff0c;Vite 需要 Node.js 版本 18 或 20 我之前是 14.16.1&#xff0c;更换成 20.0.0 就可…

Flink 06 聚合操作入门学习,真不难

抛砖引玉 让你统计1小时内每种商品的销售额&#xff0c;用Flink 该怎么实现。 还是让你统计1小时内每种商品的销售额&#xff0c;但是要过滤掉退款的订单&#xff0c;用Flink 该怎么实现。 学了本文两个操作&#xff0c;不信你还不会。 AggregateFunction ❝ 通常用于对数据…