不能直接用contenteditable替代富文本编辑器,因其粘贴不可控、换行标签不一致、execCommand已废弃、光标定位与撤销行为不可靠;TinyMCE适合快速接入且自带图片上传回调,CKEditor 5需严格配置表单绑定与模块化toolbar,二者均需前后端协同清洗HTML并防御XSS。
contenteditable 替代富文本编辑器它连基础粘贴都不可控:Word 粘贴进来一堆嵌套 <span style="font-family: Calibri">,Firefox 和 Chrome 对 Enter 键生成 <div> 还是 <p> 不一致,document.execCommand 已被废弃且行为随机。更关键的是——你没法可靠地把光标定位到加粗文字中间再按 B 键,也没法实现 Ctrl+Z 三次后光标停在哪这种细节。所谓“能打字”不等于“能交付”。
TinyMCE 和 CKEditor 5 在企业项目里怎么选看团队对可控性的要求:
TinyMCE:适合已有后端上传逻辑、只需快速接入的场景。它的 images_upload_handler 直接接收 blob,返回 URL 后自动插入;但插件生态松散,升级时容易因某一个第三方插件中断构建CKEditor 5:必须用 ClassicEditor.create(),不能用 InlineEditor(后者不绑定表单);默认输出 HTML,但如果后端只读 req.body.content,而前端没同步值或没设 name 属性,就会丢格式;模块化强,但自定义 toolbar 需写 config.toolbar.items 数组,不是字符串不是编辑器问题,是链路断在中间:
data:image/png;base64 写进 HTML —— 后端通常拒收,因为体积大、无防盗链、无法 CDN 缓存SimpleUploadAdapter 配置里漏了 uploadUrl 或响应没返回 { default: "https://..." } 结构images_upload_handler 函数里没调 success(uploadUrl),或者用了 failure(errorMessage) 但没 catch 错误导致静默失败前端传的是 HTML 字符串,后端默认可能只解析 application/x-www-form-urlencoded 或 multipart/form-data 里的文本字段,而忽略 text/html 类型:
立即学习“前端免费学习笔记(深入)”;
body-parser:加 type: 'text/*',否则 req.body.content 是空的@RequestBody String content 能接住,而不是被 Jackson 当 JSON 解析报错editor.getData() 返回的原始 HTML,先过一遍 DOMPurify.sanitize()