如果你想让 HTML 文本域只能接收纯文本、彻底禁止用户粘贴图片,关键做法就是:拦截 paste 粘贴事件、只提取 text/plain 纯文本内容、过滤 HTML 和图片数据,并结合 input 事件校验以及服务端严格清洗,形成完整防护。

要让 HTML 文本域(例如 textarea 或 contenteditable 元素)只允许输入纯文本、禁止粘贴图片,核心思路是:**拦截粘贴操作、强制获取纯文本、阻止富文本 / HTML / 图片内容混入**。仅靠 HTML 属性或 CSS 样式无法实现这一目标,必须借助 JavaScript 事件监听与内容校验来控制。
使用 textarea 时:监听 paste 事件并过滤内容
textarea 虽然原生不支持富文本编辑,但用户依然可能粘贴带格式的文本内容(包含隐藏的 HTML 标签),个别浏览器甚至可能把截图转换为 base64 图片字符串后插入(虽然这种情况较少见)。更稳妥的实现方式包括:
- 给
textarea绑定paste事件,并在第一时间执行event.preventDefault() - 通过
event.clipboardData.getData('text/plain')读取剪贴板中的纯文本内容 - 插入前先进行基础清洗,例如去除首尾空白、限制换行数量,再使用
el.value += text或insertAtCaret()插入 - 额外监听
input事件,检查el.value中是否包含<、>或 base64 特征字符串(如data:image/),一旦发现就立即截断、替换或清理
使用 contenteditable 时:必须更主动地防御
contenteditable 元素天生支持 HTML 内容,因此更容易出现粘贴富文本或图片的情况。不能只依赖禁用右键或禁止拖拽,因为这些方式对粘贴行为并不起作用。更关键的处理方式包括:
- 直接在目标元素上监听
paste事件,不要只委托到 document - 遍历
event.clipboardData?.items,如果发现item.type.startsWith('image/'),就立即执行preventDefault() - 如果
items不可用(例如旧版 Safari),则回退到getData('text/plain'),并主动丢弃 HTML 版本内容 - 粘贴后使用延迟清理(
setTimeout(() => { ... }, 0)),扫描并删除新插入的标签或内联 style 样式 - 结合
input事件持续校验,只保留文本节点,更新内容时优先使用textContent而不是innerHTML
统一兜底方案:服务端校验绝不能省略
前端拦截能够提升输入体验,但不能替代服务端安全防护。用户完全可以通过 DevTools 手动修改 DOM、绕过前端 JS,或者直接使用 curl 提交包含图片的 HTML 数据。因此建议:
- 提交前在前端再次执行一次
textContent提取,而不是直接读取innerHTML - 后端接收数据时,严格去除所有 HTML 标签,过滤
data:URI,并拒绝img、script、style等高风险标签 - 同时对内容长度、字符集范围(如是否禁止 emoji 或控制字符)进行白名单校验
移动端兼容性处理要点
iOS Safari 和部分 Android WebView 对 paste 事件的支持并不稳定,尤其在某些输入场景下可能无法正常触发,因此需要做好兼容处理。可参考以下策略:
- 不要依赖单一事件,建议组合监听
paste、input和compositionend - 在
input回调中检测异常字符(例如零宽空格、U+200B)以及非正常键盘输入符号,并及时清理 - 避免继续使用已废弃的
document.execCommand,改用getSelection()+Range来插入纯文本
