不能用 innerHTML.replace() 做高亮,因其会引发 XSS、正则误匹配、DOM 结构撕裂、高对比度/深色模式失效及可访问性丢失;必须用 Range API 原位包裹选区并显式样式适配。

window.getSelection() 返回的是真实选区,不是字符串;直接用它做正则替换必然错位、撕裂 DOM、触发 XSS。必须用 Range 和 mark 原位包裹,否则高亮不可逆、不可访问、不兼容高对比度模式。
为什么不能用 innerHTML.replace() 做高亮
这是最常踩的坑:拿到 window.getSelection().toString() 后,遍历所有元素,对 innerHTML 做全局字符串替换。
- 用户选中 “
<script></script>” → 正则注入,执行 XSS - 用户选中 “a.b” →
new RegExp("a.b")中的.被当通配符,匹配任意字符 - 原文是
→ 替换后变成Hello world
,DOM 结构被破坏,Hello world
em标签被截断 - 在 Outlook 邮件或 Windows 高对比度模式下,
无显式样式即完全不可见
正确做法:用 Range API 精准包裹选区
浏览器原生支持把当前选区转为 Range,再用 mark 包裹——不碰 HTML 字符串,不破坏节点结构,天然防 XSS、保语义、可逆清除。
生成可在 deepbi 沙箱 iframe 内运行或作为独立文件运行的交互式 HTML 页面,使用 `window.deepbi` JS SDK 实现数据查询、空间管理、文件浏览及用户操作。当用户提出以下需求时启用该能力: - 创建 KPI 仪表盘、数据表格、文件浏览器、成员列表、管理页面; - 明确要求“转成 dhtml”、“转译成 HTML”、“把 XX 页面转成……”、“控制台页面”、“管理后台”、“DeepBI 页面迁移”; - 提及位于 `apps/console/src/featur
- 监听
mouseup或selectionchange,避免在输入中误触发 - 用
getSelection().getRangeAt(0)拿到首个选区(多选暂不考虑) - 调用
range.cloneContents()备份原始内容,便于后续清除 - 新建
mark元素,mark.textContent = range.toString() - 用
range.surroundContents(mark)原位包裹 —— 注意:该方法要求 range 必须完全落在单个文本节点内,否则抛错;实际可用range.extractContents()+mark.appendChild()+range.insertNode()组合兜底
清除高亮时别漏掉嵌套 mark
用户反复选中不同文本,容易产生 text。只删 class="highlight" 没用,得递归清理所有 mark 标签并还原其 textContent。
- 清除前先缓存所有
mark的父节点和位置索引,否则removeChild()后无法精确定位 - 不要用
document.querySelectorAll('mark')后逐个remove()—— 这会跳过动态插入的、尚未挂载的mark - 推荐方式:遍历所有文本节点,对每个含
mark父辈的文本节点,用node.parentNode.replaceChild(document.createTextNode(node.textContent), node)逐个还原 - 若页面有 Shadow DOM,需额外调用
shadowRoot.querySelectorAll('mark')
深色模式与可访问性必须手动适配
mark 没有默认暗色样式,纯靠 UA 样式,在深色主题下极易变成黑底黑字;且高对比度模式下背景会被强制重置,文字失去语义提示。
- 必须显式声明
background-color和color,例如:mark { background-color: #fff9c4; color: #1f2329; } - 加
@media (prefers-color-scheme: dark)重定义颜色,避免依赖系统级 fallback - WCAG 要求文本与背景对比度 ≥ 4.5:1,黄底白字在深色模式下大概率不达标,建议改用橙/蓝系高亮色
- 盲人用户依赖
mark的语义(role="mark"已被部分读屏器识别),但若你用span class="highlight"就彻底丢失该能力
真正难的不是“怎么让字变黄”,而是让高亮在 XSS、DOM 撕裂、深色模式、高对比度、读屏器、Shadow DOM、动态加载等所有真实场景下都稳住 —— 这些细节不处理,上线后第一波用户投诉就来自邮件客户端和残障人士支持团队。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!










