富文本编辑器痛点拆解¶
难点:评论、公告、IM、低代码表单都要富文本。但原生 contenteditable 是"前端三大天坑之一":光标乱跳、粘贴带脏样式、回车产生 <div> 还是 <p>、"全选删除"后块结构崩溃、XSS 注入。
最佳实践:别从零造轮子。生产用 TipTap(ProseMirror)/ Lexical / Slate / Quill,它们用"文档模型(Schema)"而非裸 DOM,光标与结构是受控的。本 demo 用 contenteditable 演示坑在哪。
关键点(生产级细节)
- 光标保活:
execCommand执行前要在按钮mousedown调e.preventDefault(),否则焦点跑到按钮上、格式应用到错位置(demo 已处理)。 execCommand已废弃:Chrome 仍支持但标准废弃,且无法清除内联style;新编辑器走 Selection API + 自定义命令。- XSS 是红线:富文本存储的 HTML 渲染前必须
DOMPurify.sanitize()过滤on*属性与<script>;前端输出绝不能直出innerHTML(demo 的"模拟粘贴带脚本"按钮演示了<img onerror>危害)。 - 粘贴净化:监听
paste事件,clipboardData取纯文本或清洗后document.execCommand('insertHTML');禁止直接insertHTML原始 HTML。
踩坑
contenteditable在空块回车生成<div><br></div>层层嵌套,字数统计/序列化全乱 → 模型化编辑器统一成<p>。- 中文输入法(IME)组合输入
compositionstart/end期间不能做校验,否则吞字。 - 协同编辑(多人同时改)要上 CRDT(Yjs),纯 innerHTML 同步会互相覆盖。