极致体验!一个小工具实现智能关键词高亮 (中英文混排/全字匹配)

🚀 极致体验!一个小工具实现智能关键词高亮 (中英文混排/全字匹配)

在前端开发中,"关键词高亮"是一个看似简单实则暗坑无数的需求。

你是否遇到过这些问题?

  1. 高亮"run"却把"running"也标红了? (英文全字匹配问题)
  2. 搜索"C++"导致正则报错崩溃? (特殊字符转义问题)
  3. 中文关键词死活匹配不上? (正则边界问题)
  4. dangerouslySetInnerHTML 总是提心吊胆? (XSS 安全问题)

今天,我将分享一个 不到 40 行代码 的终极解决方案 markWords。它不仅完美解决了上述所有问题,还支持 React 虚拟 DOM 直接渲染!


✨ 核心亮点

  • 智能匹配:英文自动开启"全字匹配",中文自动开启"模糊匹配"。
  • 安全无毒 :返回 React Node 数组,拒绝 dangerouslySetInnerHTML
  • 正则健壮 :自动转义 ?+* 等正则特殊字符。
  • 零依赖:不需要引入任何第三方库 (lodash, highlighting, etc)。

🛠️ 源码解析

直接将以下代码复制到你的 utils.ts 中:

ts 复制代码
import React from 'react';

/**
 * 智能标记文本中的关键词
 * 
 * 特性:
 * 1. 英文单词 -> 全字匹配 (如 "run" 不会匹配 "running")
 * 2. 中文/符号 -> 模糊匹配
 * 3. 自动转义正则特殊字符
 * 4. 返回 ReactNode 数组,安全无 XSS 风险
 *
 * @param {string} text - 原始文本
 * @param {string[]} words - 关键词数组
 * @param {string} highlightClass - 高亮类名
 */
export const markWords = (text, words, highlightClass = 'highlight') => {
  if (!text || !words || words.length === 0) {
    return [text];
  }

  // 1. 构造智能正则
  const pattern = words
    .map(word => {
      // 转义特殊字符,防止正则报错
      const escaped = word.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
      
      // 核心魔法:如果是纯英文/数字单词,加上 \b 边界实现全字匹配
      // 否则(如中文),直接匹配
      if (/^\w+$/.test(word)) {
        return `\\b${escaped}\\b`;
      }
      return escaped;
    })
    .join('|');
    
  if (!pattern) return [text];

  // 2. 全局忽略大小写匹配
  const regex = new RegExp(`(${pattern})`, 'gi');
  const parts = [];
  let lastIndex = 0;
  let match;

  // 3. 循环切割文本
  while ((match = regex.exec(text)) !== null) {
    // 推入普通文本
    if (match.index > lastIndex) {
      parts.push(text.slice(lastIndex, match.index));
    }
    // 推入高亮节点 (使用 React.createElement)
    parts.push(
      React.createElement('span', { key: match.index, className: highlightClass }, match[0])
    );
    lastIndex = match.index + match[0].length;
  }

  // 推入剩余文本
  if (lastIndex < text.length) {
    parts.push(text.slice(lastIndex));
  }

  return parts.length > 0 ? parts : [text];
};

💡 效果演示

场景一:英文全字匹配

关键词:["test"] 文本:"This is a test case for testing."

  • 结果 :只有 test 被高亮,testing 中的 test 不会被误伤。

场景二:中文混合匹配

关键词:["苹果", "Apple"] 文本:"我喜欢吃苹果,因为Apple很好吃。"

  • 结果苹果Apple 都会被精准高亮。

场景三:特殊字符

关键词:["C++"] 文本:"C++ is a powerful language."

  • 结果 :正则自动转义 +C++ 完美高亮,程序不会崩。

📖 最佳实践

在组件中直接调用即可,就像使用普通的字符串一样:

tsx 复制代码
import { markWords } from '@/utils/util';
import styles from './index.module.scss';

const Article = ({ title, content, searchKeyword }) => {
  return (
    <div className={styles.card}>
      {/* 高亮标题 */}
      <h3>{markWords(title, [searchKeyword], styles.highlight)}</h3>
      
      {/* 高亮正文 */}
      <p>{markWords(content, [searchKeyword], styles.highlight)}</p>
    </div>
  );
};**别忘了定义 CSS:**
.highlight {
  color: #ff4d4f;
  background-color: #fff1f0;
  font-weight: bold;
  border-radius: 2px;
}

📝 总结

这个小工具虽然简单,但细节满满。它在保证 安全性 的前提下,兼顾了 中英文语言特性代码健壮性

把这个函数收藏进你的代码片段库(Snippets),以后遇到高亮需求,一秒搞定!💪

相关推荐
yujunlong39194 小时前
Redux Toolkit (RTK) + TypeScript
前端·typescript·react
未来之窗软件服务5 小时前
幽冥大陆(五十二)V10酒店门锁SDK TypeScript——东方仙盟筑基期
前端·javascript·typescript·酒店门锁·仙盟创梦ide·东方仙盟·东方仙盟sdk
Hao_Harrision5 小时前
50天50个小项目 (React19 + Tailwindcss V4) ✨| BackgroundSlider(背景滑块)
前端·typescript·react·vite7·tailwildcss
by__csdn16 小时前
Vue3 setup()函数终极攻略:从入门到精通
开发语言·前端·javascript·vue.js·性能优化·typescript·ecmascript
濮水大叔21 小时前
VonaJS是如何做到文件级别精确HMR(热更新)的?
typescript·node.js·nestjs
刘发财1 天前
前端一行代码生成数千页PDF,dompdf.js新增分页功能
前端·typescript·开源
黛色正浓1 天前
【React18+TypeScript】React 18 for Beginners
javascript·react.js·typescript