用<mark>标签配合JavaScript实现搜索高亮,需转义关键词、遍历文本节点替换、防嵌套、缓存原始HTML并优化性能。

用 <mark> 标签配合 JavaScript 实现搜索高亮,核心在于:先获取目标文本内容,再用正则匹配关键词,最后用 <mark> 包裹匹配部分并替换回 DOM。关键要注意转义特殊字符、区分大小写、避免重复嵌套和保留原有 HTML 结构。
提取并安全处理搜索关键词
用户输入的关键词可能含正则元字符(如 .、*、?),直接用于 RegExp 会出错。需先转义:
- 用
String.replace(/[-/\^$*+?.()|[]{}]/g, '\$&')对关键词做转义 - 若需忽略大小写,构造正则时加
i标志;否则用g全局匹配即可 - 建议对空关键词或空白字符串提前返回,避免无效操作
定位文本节点并执行替换
不能直接对整个元素的 innerHTML 操作,否则会破坏事件绑定、表单状态或内联脚本。应遍历文本节点:
- 用
NodeIterator或递归遍历childNodes,筛选出Node.TEXT_NODE - 对每个文本节点内容执行
String.prototype.replace(),用<mark>$</mark>替换匹配项 - 替换后生成新 HTML 片段,用
document.createElement('template')安全插入,避免 XSS
防止 mark 嵌套和样式冲突
多次高亮同一区域会导致 <mark><mark>xxx</mark></mark>,既冗余又影响样式。解决方法:
立即学习“Java免费学习笔记(深入)”;
- 高亮前先移除已有
<mark>,可用element.querySelectorAll('mark').forEach(m => m.replaceWith(m.textContent)) - 给
mark加 CSS 类(如.search-highlight),便于统一控制背景色、padding 和 z-index - 若容器有
overflow: hidden,给mark加vertical-align: middle防止截断
支持取消高亮与性能优化
用户清空搜索框或切换关键词时,应还原原始内容。推荐保存原始文本快照:
- 首次渲染时用
element.dataset.originalHtml = element.innerHTML缓存原始结构 - 取消高亮时直接赋值还原,比反向解析
mark更可靠 - 对长列表或大量文本,可加节流(如
setTimeout延迟执行)或只处理可视区域内的节点


















