应使用document.createtreewalker()遍历纯文本节点进行高亮,避免innerhtml.replace()破坏dom结构、丢失事件和表单值,并用unicode边界正则防止中文误匹配。

为什么直接 innerHTML.replace() 会破坏表格结构
表格里有 <input>、<select></select>、<button></button> 等交互元素,用 innerHTML.replace() 一执行,整个 <tr> 的 HTML 字符串被重写,所有已绑定事件丢失,表单值清空,甚至 <code><img src="a.jpg"> 可能被切进 <mark></mark> 里变成 <img src="<mark>a</mark>.jpg"> —— 图片直接挂掉。
常见错误现象包括:
- 点击搜索后,表格里的下拉框无法再展开
- 用户刚输入的数值在
<input value="123">里瞬间变空 - 高亮完再点一次搜索,
<mark></mark>嵌套出现:<mark><mark>关键词</mark></mark>
如何只操作表格里的纯文本节点
必须绕过 HTML 字符串,只处理真实的人类可读文本。核心是用 document.createTreeWalker() 遍历 NodeFilter.SHOW_TEXT 类型节点,并跳过非内容区域。
实操建议:
- 从表格容器开始:const table = document.getElementById('myTable'); const walker = document.createTreeWalker(table, NodeFilter.SHOW_TEXT, null, false);
- 过滤掉无效节点:if (!node.textContent.trim() || node.parentElement?.tagName === 'SCRIPT' || node.parentElement?.tagName === 'STYLE' || node.parentElement?.tagName === 'TEXTAREA') continue;
- 对每个
node.textContent执行正则匹配,而不是整个innerHTML - 匹配后创建
mark元素:const mark = document.createElement('mark'); mark.textContent = matchedText; node.parentNode.replaceChild(mark, node);
中文关键词怎么避免“服务”匹配到“服务器”
中文无空格分隔,/服务/gi 会把“微服务架构”切开成“微服务架构”,语义断裂。不能靠简单正则解决,但可用 Unicode 边界模拟缓解。
推荐正则写法(需先转义关键词):
const escaped = keyword.replace(/[.*+?^${}()|[]\]/g, '\$&');
const reg = new RegExp(`(?
<p>说明:</p>
(? 是正向先行断言,不消耗字符,只检查左侧是否为汉字、空白或行首-
(?=...)同理检查右侧边界 - 仍会漏掉“服务费”“服务商”等复合词,但比全局匹配可读性高得多
高亮后表格样式错乱或 mark 不显示
<mark></mark> 标签本身没有可靠默认样式——Safari 阅读模式剥离它,Windows 高对比度模式重置背景色,深色主题下默认黄色 (#ff0) 完全不可见。
必须显式声明 CSS:
mark {
background-color: #ffeb3b;
color: #212121;
padding: 0.1em 0.3em;
border-radius: 3px;
}
@media (prefers-color-scheme: dark) {
mark {
background-color: #ffca28;
color: #121212;
}
}
注意:mark 是语义标签,不是视觉装饰,不能用 <span class="highlight"></span> 替代——读屏器依赖它识别搜索上下文,替换会损害可访问性。
真正容易被忽略的是:高亮后要调用 node.parentNode.normalize() 合并相邻文本节点,否则连续两次搜索同一词,会产生多个孤立 mark 节点,后续再匹配可能失效。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











