应使用 document.createTreeWalker() 遍历纯文本节点并高亮,避免 innerHTML.replace() 重建 DOM 导致表单值清空、事件丢失和属性污染;需过滤脚本/样式/文本域节点,对文本内容用带 Unicode 边界判断的正则匹配并包裹 mark 元素。

直接用 innerHTML.replace() 会清空表单值、丢失事件
表格里有 <input>、<select> 或带 onclick 的按钮时,innerHTML.replace() 会把整个 <tr> 字符串重写一遍。结果是:value 瞬间变空、下拉框无法再点开、mark 嵌套进 src 属性里(比如 <img src="<mark>a</mark>.jpg">),图片直接 404。
这不是“高亮没生效”,而是 DOM 被暴力重建了。只要表格含交互元素,就绝不能走字符串替换这条路。
document.createTreeWalker() 只处理纯文本节点
必须绕过 HTML 字符串,只改人眼可见的文本内容。核心是创建一个只遍历 NodeFilter.SHOW_TEXT 的树遍历器:
- 从表格容器开始:
const table = document.getElementById('myTable');,再调用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 - 匹配后用
document.createElement('mark')替换该文本节点,不碰父元素结构
中文关键词要防“服务”匹配到“服务器”
全局 /服务/gi 会把“微服务架构”切开成“微服务架构”,语义断裂。得加 Unicode 边界判断:
立即学习“前端免费学习笔记(深入)”;
先转义关键词:const escaped = keyword.replace(/[.*+?^${}()|[\]\]/g, '\$&');
再构造正则:const reg = new RegExp(`(?
说明:(? 检查左侧是否为汉字、空白或行首,<code>(?=...) 同理检查右侧——不消耗字符,只校验位置。它仍无法识别“服务商”这类复合词,但比无边界匹配可读性高得多。
<mark> 默认样式在深色主题/高对比度下完全不可见
<mark> 没有跨浏览器一致的默认背景色:Safari 阅读模式可能剥离它,Windows 高对比度模式会重置背景,深色主题下原生黄色 #ff0 和背景融为一体。
必须显式声明 CSS:
mark {
background-color: #ffeb3b;
color: #212121;
padding: 0 2px;
border-radius: 2px;
}
否则用户根本看不到高亮,还以为功能坏了。这个样式要加在全局 CSS 里,不能只靠 scoped 或内联。



















