sanitizer api 返回 documentfragment 而非字符串,需用 replacechildren 或 appendchild 插入;容器类型决定过滤规则;须检测 typeof sanitizer !== 'undefined' 并降级;sethtml 封装 sanitizefor 但环境限制更隐蔽。

Sanitizer API 不是“开箱即用”的字符串清洗工具,直接 sanitizeFor('div', html) 返回的是 DocumentFragment,不是 HTML 字符串——这是绝大多数人踩坑的第一步。
sanitizeFor 返回 DocumentFragment,不是字符串
很多人写 el.innerHTML = sanitizer.sanitizeFor('div', dirty),结果页面空白或内容错乱。因为 sanitizeFor 返回的是一个真实 DOM 片段对象,不能直接赋值给 innerHTML。
- ✅ 正确转字符串(仅当结构简单、预期单根时):
frag.innerHTML - ✅ 更推荐直接插入:
el.replaceChildren(frag)或el.appendChild(frag),避免二次解析风险 - ❌ 禁止链式调用:
sanitizeFor('div', s).innerHTML.innerHTML会报错 - ⚠️ 注意:
frag.innerHTML只取 fragment 内部所有子节点的序列化 HTML,不包含外层容器标签(如你传了'div',返回的 fragment 并不自带<div>...</div>)
容器类型(第一个参数)决定过滤行为
sanitizeFor('span', html) 和 sanitizeFor('div', html) 的净化结果可能完全不同——这不是“随便包个 div 就行”,而是上下文感知过滤。
-
'span':拒绝块级元素(<p></p>、<div>),自动降级或剥离<li> <code>'div':允许嵌套块元素,但严格过滤on*属性、危险style值、javascript:URL -
'template':保留内容但不执行脚本,适合预编译场景 - 别硬写死
'div';根据你最终要挂载的目标语义选,比如渲染到<article></article>就用'article' - ✅ 检测方式:
typeof Sanitizer !== 'undefined'(不是typeof window.Sanitizer) - ✅ 降级方案:检测失败时,可 fallback 到
DOMPurify.sanitize()或原样返回(需权衡安全等级) - ⚠️ 注意:Chrome 125+ 默认启用,但本地
http://localhost下 SVG 等元素仍可能被误删——HTTPS 环境才保证完整能力 - ⚠️ ESLint 会报
Sanitizer is not defined,需在文件头加/* global Sanitizer */或配置globals: { Sanitizer: 'readonly' } -
el.setHTML(dirty, { sanitizer }):自动创建临时容器、净化、清空el、插入结果;适合快速替换整个元素内容 -
sanitizer.sanitizeFor('div', dirty):返回DocumentFragment,由你决定怎么用——更适合细粒度控制(如只更新某部分、配合 React 渲染) - ⚠️
setHTML在非 HTTPS 下可能静默失败(尤其含<svg></svg>时),而sanitizeFor会抛错,更容易发现问题
必须运行时检测 Sanitizer 是否可用
new Sanitizer() 在 Safari、Firefox(未开启实验功能)和所有 Node.js 环境中直接抛 ReferenceError,导致 JS 中断、页面白屏。
setHTML 与 sanitizeFor 的关键区别
Element.prototype.setHTML 是另一个实验性方法,它内部调用 sanitizeFor,但封装了容器创建逻辑;而 sanitizeFor 更底层、更可控。
真正难的不是调用 API,而是理解它返回的是 DOM 节点而非字符串、它的过滤规则随容器类型动态变化、以及它对协议和运行环境有隐式依赖——这些细节一旦忽略,安全就只是假象。











