最直接的方式是用 string.prototype.replace() 配合转义后不区分大小写的全局正则,将关键词包裹为带样式的 span;需防 xss,优先处理长关键词,并缓存正则、限制匹配次数以优化性能。

最直接的方式是用 String.prototype.replace() 配合正则表达式,把目标文本替换成带高亮标签的 HTML 片段。
基础实现:关键词包裹 + 内联样式
核心逻辑是将匹配到的关键词用 <span></span> 包裹,并添加背景色或 class。注意需转义特殊正则字符,避免报错。
- 构造不区分大小写的全局正则:
new RegExp(keyword.replace(/[.*+?^${}()|[]\]/g, '\$&'), 'gi') - 用
replace()的函数参数方式返回高亮 HTML:str.replace(reg, match => `<span style="background-color: #ffeb3b;">${match}</span>`) - 替换后必须用
innerHTML渲染(不能用textContent),否则标签会被当作文本显示
安全增强:防 XSS 与 HTML 结构保留
若原始文本含 HTML 标签(如 <p>搜索<b>关键词</b></p><div class="aritcle_card flexRow artxards">
<div class="artcardd flexRow">
<a class="aritcle_card_img" rel="nofollow" href="/xiazai/skill8078" title="Wjs Uploading Video"><img
src="https://img.php.cn/upload/skill/000/000/081/179185692016044.jpg" alt="Wjs Uploading Video" onerror="this.onerror='';this.src='/static/lhimages/moren/morentu.png'" ></a>
<div class="aritcle_card_info flexColumn">
<a rel="nofollow" href="/xiazai/skill8078" title="Wjs Uploading Video" class="overflowclass">Wjs Uploading Video</a>
<p class="overflowclass">将一个或多个视频上传至YouTube。当用户想“上传到YouTube”“发YouTube”“批量上传”“upload to YouTube”“post videos to YouTube”或发布到YouTube时使用此技能。</p>
</div>
<a rel="nofollow" href="/xiazai/skill8078" title="Wjs Uploading Video" class="aritcle_card_btn flexRow flexcenter"><b></b><span>下载</span>
</a>
</div>
</div>),直接正则替换会破坏结构。此时应:
- 先用
DOMParser解析为文档节点,再遍历文本节点处理 - 对每个文本节点执行高亮,用
document.createTextNode()和element.insertBefore()插入新节点 - 或使用
DOMPurify.sanitize()过滤结果,防止注入恶意脚本
多关键词支持:按长度排序避免误包
当同时高亮 #tag 和 #tagAgain 时,若先处理短词,#tag 可能错误地包在 #tagAgain 中间。解决方法是:
- 将关键词数组按字符串长度降序排列:
keywords.sort((a, b) => b.length - a.length) - 逐个执行
replace(),确保长关键词优先匹配 - 若需统一管理样式,可提前定义 CSS 类(如
.highlight-1),再通过class属性动态赋值
性能优化:避免重复渲染与过度匹配
高频调用(如输入实时搜索)下,需控制开销:
- 对同一字符串多次高亮时,缓存正则实例,避免重复
new RegExp - 限制匹配次数,例如加
{0, 100}量词,防超长文本卡顿 - 用
requestIdleCallback延迟非关键高亮操作,保证主线程响应流畅










