必须拦截paste事件并调用event.preventdefault(),再用domparser解析text/html、白名单过滤节点、移除style/class属性,避免xss;innertext和正则无法可靠清洗。

contenteditable 粘贴时执行 script 标签怎么办
直接监听 paste 事件但不调用 event.preventDefault(),浏览器就会原样插入剪贴板里的 HTML —— Word、微信、Notion 复制的内容常带 <script></script>、<style></style> 或内联 onerror 属性,一插入就触发 XSS。
必须拦截并清洗,不能依赖 innerText 或正则删标签:
-
innerText会丢换行、吞零宽字符(如\u200b),且无法控制语义结构 - 正则
/]*>/g删不掉注释、CDATA、自闭合标签里的危险属性(如<img src="x" onerror="alert(1)">) - 优先取
event.clipboardData.getData('text/html'),用DOMParser解析成文档片段,再白名单遍历节点 - 只保留
p、br、strong、em、ul、ol、li;对所有保留节点调用removeAttribute('style')和removeAttribute('class')
为什么加了 contenteditable="true" 还是点不动或 Tab 不进
根本原因:可编辑 ≠ 可聚焦。div、td 等非表单元素默认没有 tabindex,键盘无法抵达,也就没法触发快捷键(Ctrl+B)、Selection API 或 document.execCommand。
漏掉这步,用户点鼠标能打字,但所有富文本操作都失效:
如果你了解HTML,CSS和JavaScript,您已经拥有所需的工具开发Android应用程序。本动手本书展示了如何使用这些开源web标准设计和建造,可适应任何Android设备的应用程序 - 无需使用Java。您将学习如何创建一个在您选择的平台的Android友好的网络应用程序,然后转换与自由PhoneGap框架到一个原生的Android应用程序。了解为什么设备无关的移动应用是未来的潮流,并开始构建应用程序,提供更
- 必须显式加
tabindex="0"(推荐)或tabindex="-1"(仅 JS 可 focus) - 父容器若设了
contenteditable="false",子元素写contenteditable="true"也无效——“就近 false 优先” - 值必须是字符串
"true",写成contenteditable="1"或contenteditable="on"是无效的,浏览器当它不存在 - Safari 旧版对空值
contenteditable(无等号)支持不稳定,务必写全
IE11 / Safari 表格单元格编辑异常怎么绕
contenteditable 在 <td> 上不是标准用法,IE11 完全不支持,Safari(尤其 iOS)存在光标错位、input 事件不触发、虚拟键盘遮挡等问题。
<p>硬扛兼容性只会拖慢迭代节奏:</p>
<ul><li>不要在 <code><th> 上启用,部分浏览器拒绝聚焦
<li>检测运行环境:<code>if (!document.execCommand || /iPad|iPhone|iPod/.test(navigator.userAgent)),命中即降级为点击时动态插入 <input> 或 <textarea></textarea>
<div> 或换行,业务上通常要改为“保存 + 聚焦下一单元格”,必须 <code>event.preventDefault() 后手动计算 table.rows[rowIndex].cells[nextColIndex]
cell.innerHTML),再调用 cell.blur() 清除编辑态MutationObserver 监听内容变化却漏掉粘贴怎么办
MutationObserver 能捕获 DOM 变更,但粘贴动作完成得比 observer 回调还快——尤其 Safari 中,observer 可能拿到的是清洗前的污染 DOM。
监听时机错了,安全逻辑就形同虚设:
- 不能只靠
input或blur:它们在粘贴完成之后才触发,污染已落地 - 必须在
paste阶段拦截,且event.preventDefault()是第一行代码 - 清洗后插入,要用
getSelection().getRangeAt(0)获取光标位置,range.deleteContents()清空选区,再range.insertNode(textNode)插入干净文本 - IE11 不支持
insertNode(),需 fallback 到range.createContextualFragment()或字符串拼接
真正难的不是写清洗逻辑,而是所有浏览器里光标位置、粘贴源格式、事件触发时序都不一致。一个 contenteditable 元素上线前,至少要在 Chrome、Firefox、Safari(含 iOS)、Edge 四个环境里分别验证 paste、Enter、Tab、Escape、focus/blur 的行为是否收敛。否则,看似修了一个 XSS,结果在 Safari 里光标永远卡在开头。










