不能用 innerHTML.replace() 处理问答内容,因其会破坏嵌套结构、引入 XSS 风险、丢失事件与状态、导致中文误匹配;应使用 TreeWalker 安全操作纯文本节点。

mark 是唯一符合语义、安全且可访问的动态高亮方式,其他方案(如 innerHTML.replace 或 span.highlight)在搜索结果、问答页等上下文敏感场景中会破坏可访问性、引入 XSS 风险或导致 DOM 崩坏。
为什么不能用 innerHTML.replace() 处理问答内容?
问答内容通常混有 HTML 标签(如 <strong></strong>、<a></a>)、用户输入文本和动态插入的节点。直接对 innerHTML 正则替换会导致:
- 嵌套结构错乱:原始
<strong>React</strong> Native可能被替成<mark><strong>React</strong></mark> Native,mark包裹了整个元素,语义失效 - XSS 漏洞:若关键词来自 URL 参数(如
q=<script>alert(1)</script>),拼进字符串再赋值给innerHTML会直接执行脚本 - 事件与状态丢失:表单值、
input光标位置、绑定的onclick监听器全部清空 - 中文误匹配:正则
/服务/gi会把“服务器”“微服务”全标出,而实际只需独立词“服务”
如何用 TreeWalker 安全高亮纯文本节点?
核心是绕过字符串拼接,只操作真实文本节点(Node.TEXT_NODE),保留原有 DOM 结构和交互能力:
生成可在 deepbi 沙箱 iframe 内运行或作为独立文件运行的交互式 HTML 页面,使用 `window.deepbi` JS SDK 实现数据查询、空间管理、文件浏览及用户操作。当用户提出以下需求时启用该能力: - 创建 KPI 仪表盘、数据表格、文件浏览器、成员列表、管理页面; - 明确要求“转成 dhtml”、“转译成 HTML”、“把 XX 页面转成……”、“控制台页面”、“管理后台”、“DeepBI 页面迁移”; - 提及位于 `apps/console/src/featur
- 创建
TreeWalker,过滤类型为NodeFilter.SHOW_TEXT,跳过元素/注释节点 - 对每个文本节点调用
textContent.matchAll(),用带 Unicode 边界的正则(如/(?)精准匹配中文词 - 用
Range.surroundContents()把匹配段落包裹进新mark节点 —— 不重建父容器,不丢失光标 - 关键词需提前
escapeHtml()转义:处理&、、<code>"等字符,避免 DOM 解析中断
mark 样式必须显式声明哪些属性?
浏览器默认样式不可交付,尤其在邮件客户端、阅读模式、Windows 高对比度或暗色主题下会完全失效:
立即学习“前端免费学习笔记(深入)”;
- 必须设置
background-color和color,不能留空或依赖继承 - 必须加
padding: 0.1em 0.3em,否则背景紧贴文字,边缘生硬且可读性差 - 建议加
border-radius: 3px和box-shadow: inset 0 -2px 0 rgba(0,0,0,0.1)提升视觉区分度 - 暗色模式下用
@media (prefers-color-scheme: dark)单独定义,比如background-color: #ffca28
真正难的不是写出高亮逻辑,而是判断「这个高亮是否承载上下文信息」——问答页里用户搜“404 错误”,所有命中处必须用 mark;但 FAQ 标题旁那个固定的「常见问题」徽章,就该用 span.badge。


















