sanitizefor 返回 documentfragment,需用 replacechildren 或 appendchild 插入 dom;容器类型影响过滤逻辑,须按目标元素选择;须检测 typeof sanitizer !== 'undefined' 以兼容旧环境。

sanitizeFor 返回 DocumentFragment,不是字符串
直接写 el.innerHTML = sanitizer.sanitizeFor('div', html) 会出问题——页面空白或内容错乱。因为 sanitizeFor 返回的是 DocumentFragment 对象,不是 HTML 字符串。
常见错误现象:
-
innerHTML赋值后什么也不显示 - 控制台没报错,但 DOM 结构丢失
- 链式调用
sanitizeFor(...).innerHTML.innerHTML报Cannot read property 'innerHTML' of undefined
正确做法分两种场景:
- 要字符串:用
frag.innerHTML(仅当预期单根元素时安全,比如传入的 HTML 本就是<p>...</p>) - 要插入 DOM:用
el.replaceChildren(frag)或el.appendChild(frag),不经过字符串序列化,避免二次解析风险
容器类型参数影响过滤逻辑,不能硬写 'div'
sanitizeFor('span', html) 和 sanitizeFor('div', html) 的结果可能完全不同。这个第一个参数不是“随便包个容器”,而是告诉 Sanitizer 当前上下文语义,从而决定哪些标签/属性能保留。
典型行为差异:
-
'span':拒绝块级元素(<p></p>、<div>),自动剥离或降级为内联等效<li> <code>'div':允许嵌套块结构,但严格过滤on*属性、javascript:URL、危险style值(如expression()) -
'template':保留内容但不执行脚本,适合预编译渲染场景 - 根据你最终挂载的目标容器选,比如渲染到
<article></article>就用'article' - 别为了“省事”统一用
'div',否则可能意外放行不该出现的结构 - 用
typeof Sanitizer !== 'undefined',不是typeof window.Sanitizer - ESLint 会报
Sanitizer is not defined,需加/* global Sanitizer */或配置globals: { Sanitizer: 'readonly' } - 降级方案可选:
DOMPurify.sanitize()、原样返回(需权衡安全等级)、或服务端 fallback - Chrome 125+ 默认启用,但本地
http://localhost下 SVG 等元素仍可能被误删;HTTPS 环境才保证完整能力 - 不要在组件初始化时就 new Sanitizer(),应延迟到首次调用前检测
-
setHTML自动创建容器并插入,隐藏了上下文选择细节,容易忽略过滤规则依赖容器类型 -
sanitizeFor显式暴露容器参数,便于精准控制过滤策略,也方便复用Sanitizer实例(避免重复初始化开销) -
setHTML在不支持环境会静默失败或回退到innerHTML,安全性不如手动检测 +sanitizeFor
使用建议:
必须运行时检测 typeof Sanitizer !== 'undefined'
在 Safari、Firefox(未开启实验功能)、所有 Node.js 环境中,new Sanitizer() 会直接抛 ReferenceError,JS 中断,页面白屏。
检测和降级要点:
额外注意:
setHTML 与 sanitizeFor 不是同一层抽象
Element.prototype.setHTML 是另一个实验性方法,它内部调用 sanitizeFor,但封装了容器创建逻辑;而 sanitizeFor 更底层、更可控。
关键区别:
建议优先用 sanitizeFor,除非你明确需要 setHTML 提供的便捷语法糖。
真正难处理的点不在 API 调用本身,而在容器语义和运行时兼容性的耦合——选错容器类型,净化就失效;漏掉检测,整个功能就崩。这两处最容易被跳过,也最难事后排查。











