不能直接用 innerhtml.replace() 做高亮,因为会破坏 dom 结构、丢失表单值、触发 xss、切开已有标签;根本原因是浏览器将 innerhtml 当纯字符串重解析,无法区分文本内容与标签结构。

为什么不能直接用 innerHTML.replace() 做高亮
因为会立刻破坏 DOM 结构、丢失表单值、执行 XSS、切开已有标签。比如搜 logo,<img src="logo.png"> 可能变成 <img src="<mark>logo</mark>.png">,图片挂掉;搜 <script>alert(1)</script> 会直接执行脚本。
根本问题在于:浏览器把 innerHTML 当纯字符串重解析,而你传进去的 <mark></mark> 片段会和原有 HTML 标签混在一起,无法区分“文本内容”和“标签结构”。
- 表单输入框(
<input value="已填内容">)高亮后清空 - 绑定的事件监听器全部失效
-
<script></script>或<textarea></textarea>内容被误匹配并污染 - 关键词卡在标签中间,如把
<b>React</b>拆成<b><mark>Re</mark>act</b>,DOM 报错
必须只操作文本节点:用 TreeWalker 安全遍历
正确做法是绕过字符串拼接,只对纯文本内容做切分与替换。核心是定位 nodeType === 3(即文本节点),跳过所有元素、注释、脚本、样式和 <textarea></textarea>。
- 用
document.createTreeWalker(element, NodeFilter.SHOW_TEXT, null, false)创建遍历器,它天然过滤非文本节点 - 循环中加守卫:
if (!node.textContent.trim() || node.parentElement?.tagName === 'SCRIPT' || node.parentElement?.tagName === 'STYLE' || node.parentElement?.tagName === 'TEXTAREA') continue - 对每个有效节点,用
node.nodeValue做正则匹配,而非整个innerHTML - 每次替换后立即调用
node.parentNode.normalize(),合并相邻文本节点,防止重复高亮
多关键词匹配必须按长度降序,且防嵌套
用户搜 ["script", "JavaScript"] 时,如果先匹配短词 script,可能把 JavaScript 拆成 Java<mark>script</mark>,语义完全错乱。
- 关键词数组必须先按字符串长度从长到短排序:
keywords.sort((a, b) => b.length - a.length) - 每个关键词都要单独转义正则元字符:
keyword.replace(/[.*+?^${}()|[]\]/g, '\$&') - 英文场景加单词边界
\b,中文则用 Unicode 边界模拟:(?,避免“服务”匹配到“服务器” - 不要用
join('|')一次性匹配——不同关键词需绑定不同 CSS 类(如mark.mark-keyword-1),否则无法区分颜色和语义
mark 标签必须显式声明样式,且兼容性极差
浏览器默认黄色背景在多数真实环境中根本不可见:Safari 阅读模式下忽略、Windows 高对比度模式强制黑底白字、深色主题下对比度低于 WCAG AA 标准、Outlook 等邮件客户端彻底禁用 UA 样式。
- 至少写清三项:
background-color、color、padding,例如:mark { background-color: #4caf50; color: white; padding: 0.1em 0.25em; border-radius: 2px; } - 深色模式需手动适配:
@media (prefers-color-scheme: dark) { mark { background-color: #ffcc00; color: #111; } } - IE 完全不识别
mark,旧版 Safari 渲染不一致,且子元素(如<strong></strong>)的color会被父级mark覆盖——这不是 bug,是 CSS 层叠规则使然 - 别用
display: inline-block或vertical-align改变mark行内行为,它可能撑开行高或破坏换行
真正的难点不在“怎么包 mark”,而在“怎么确保它只出现在该出现的地方、只包裹该包裹的文本、只影响该影响的样式”。任何跳过文本节点遍历、忽略正则转义、依赖默认样式的写法,在上线后都会暴露为偶发性 DOM 崩溃或可访问性缺陷。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











