textarea本身不支持富文本,只能接收纯文本;正确做法是拦截paste事件,阻止默认行为,手动提取text/plain或text/html内容清洗后插入,同时需服务端二次净化。

HTML文本域()本身**不支持富文本**,它只能接收纯文本。所以当你看到“在文本域中粘贴富文本并过滤样式”,实际场景通常是:用户想把 Word、网页或微信里带格式的内容粘贴进去,但期望只保留文字结构(如换行、缩进),去掉所有 HTML 标签、内联样式、脚本和冗余属性——这需要靠 JavaScript 主动拦截和清洗,而不是靠 自身能力。
为什么不能直接用 textarea 接收富文本?
的值(value)永远是纯字符串,浏览器会自动把粘贴的富文本降级为纯文本(丢掉标签,但可能残留换行、空格、零宽字符)。这种“自动降级”不可控:
- Safari 和旧 Android 可能返回空或乱码;
- Word 复制的段落可能塌成一行,首行缩进消失;
- 零宽字符(\u200b)、软连字符(\u00ad)悄悄混入,导致渲染异常或搜索失败。
正确做法:拦截 paste 事件,手动提取 clean text
别等粘贴完再“删标签”,要从源头控制数据源:
- 监听
paste事件,调用event.preventDefault() - 优先读取
event.clipboardData.getData('text/html'),用DOMParser解析成 DOM 片段——比text/plain更可靠,能识别、等语义块- 遍历节点:对块级元素(
p、div、li)后手动加\n;对连续空白用.replace(/\s+/g, ' ')压缩,再还原必要缩进- 清除零宽字符:
.replace(/\u200b|\u00ad/g, '')- 用
setRangeText()把清洗后的字符串插入光标位置(兼容 IE10+,比document.execCommand稳定)如果必须用 contenteditable 模拟富文本输入框
有些场景会用
替代,但它默认原样插入 HTML,极易引入 XSS 和样式混乱:- 绝不能跳过
paste事件拦截,否则 Word 的、微信的全部照单全收 - 禁用
document.execCommand('insertText')——已废弃,且总插到末尾 - 现代写法:用
getSelection().getRangeAt(0)获取光标位置,range.deleteContents()清空选区,再range.insertNode(textNode)插入清洗后的文本节点 - iOS 和部分安卓需降级处理:用
range.createContextualFragment()或字符串拼接
后端也得守好最后一关
前端清洗只是体验优化,不能替代服务端净化:
- 提交前可跑一次
DOMPurify.sanitize()做预览,但原始未清洗内容必须原样发给后端 - PHP 项目用
HTMLPurifier,显式配置白名单(如a[href|title], p, br, strong),禁用宽松模式 - Java 项目推荐
jsoup Safelist,对img[src]单独校验协议(只允http/https) - 绝不能用
htmlspecialchars()或strip_tags()处理富文本——前者破坏语义,后者留着onerror属性照样执行
- 遍历节点:对块级元素(
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











