纯HTML编辑器(如contenteditable)无法可靠实现富文本,因其缺乏schema约束、跨浏览器兼容性差、粘贴不可控、光标丢失及换行混乱等问题;应选用ProseMirror或Tiptap等具备文档模型与解析规则的现代方案。

富文本编辑器本质就是 HTML 编辑器
直接说结论:纯 HTML 编辑(比如 contenteditable 或 document.execCommand)能实现基础富文本,但无法可靠解决富文本——尤其涉及样式一致性、跨浏览器粘贴、语义化结构、协作编辑或服务端存储时,它会迅速暴露缺陷。
真正的问题不在“能不能写 HTML”,而在于“谁来保证这段 HTML 安全、可维护、可渲染、可回显”。原生 HTML 编辑缺乏默认的 schema 约束和解析逻辑,<div style="color:red">文字</div> 和 <span class="highlight">文字</span> 在视觉上可能一样,但语义、可访问性、后续样式覆盖能力完全不同。
用 contenteditable 做富文本的三个硬伤
这是最常被误用的“入门方案”,表面简单,实际埋雷密集:
- 粘贴行为不可控:Chrome 会带
style,Word 粘贴生成嵌套<span><b><font></font></b></span>,微信公众号复制过来甚至有data-spm属性——你没写任何逻辑,但 DOM 已经失控 - 光标位置丢失:执行
innerHTML = newHtml后,光标必然跳到开头;想保留位置得手动记录getSelection()+range,兼容 IE/Edge 的写法至今仍有差异 - 空行和换行混乱:
Enter在 Firefox 插入<br>,在 Chrome/Safari 默认插<p><br></p><div class="aritcle_card flexRow"> <div class="artcardd flexRow"> <a class="aritcle_card_img" href="/xiazai/skill10246" title="HTML Text Extract"><img src="https://img.php.cn/upload/skill/001/246/273/6adaf20dee630206.jpg" alt="HTML Text Extract" ></a> <div class="aritcle_card_info flexColumn"> <a href="/xiazai/skill10246" title="HTML Text Extract">HTML Text Extract</a> <p>从HTML页面(URL、文件或标准输入)中提取主体内容文本,去除导航、页脚、广告和模板文本。可直接传递给readability_check或其他文本工具。</p> </div> <a href="/xiazai/skill10246" title="HTML Text Extract" class="aritcle_card_btn flexRow flexcenter"><b></b><span>下载</span> </a> </div> </div> <p><span>立即学习</span>“<a href="https://pan.quark.cn/s/cb6835dc7db1" style="text-decoration: underline !important; color: blue; font-weight: bolder;" rel="nofollow" target="_blank">前端免费学习笔记(深入)</a>”;</p>,Safari 还可能把连续空行转成<div><br></div>
execCommand 已废弃,别再当“入门首选”
MDN 明确标记为 Deprecated,Chrome 97+ 已移除部分命令支持,Safari 仅保留极少数。但它仍出现在大量老教程里,导致新手踩坑:
-
document.execCommand('bold')不生成<strong></strong>,而是包裹<b></b>或内联font-weight:bold—— 与现代 CSS 体系冲突 - 无法控制作用范围:选中一段文字加粗,若其中已有
<em></em>,结果可能是<b><em>xxx</em></b>,而非语义嵌套正确的<strong><em>xxx</em></strong></li> <li>返回值不可靠:<code>execCommand
大多返回true,哪怕操作根本没生效(比如当前无选区)
真正可用的入门路径:从 ProseMirror 或 Tiptap 开始
不是推荐“学框架”,而是承认:富文本需要明确的文档模型(Document Model)+ 可序列化的操作(Transaction)+ 可预测的解析/序列化规则。这两个库都基于 ProseMirror 核心,提供清晰的抽象:
- 编辑内容不是字符串,而是
Node树(类似 AST),bold是一个 mark 类型,paragraph是一个 node 类型,彼此解耦 - 粘贴进来的内容先过
parseHTML规则,自动过滤危险标签、归一化样式、转换 Word 特有结构 - 输出可控:调用
editor.getHTML()得到干净 HTML,editor.getJSON()得到结构化数据,不依赖 DOM 快照 - 最小可行示例只需 10 行:
import { Editor } from '@tiptap/core' import StarterKit from '@tiptap/starter-kit' const editor = new Editor({ element: document.querySelector('#editor'), extensions: [StarterKit], })
复杂点在于节点定义和粘贴规则要自己配,但比起手搓 contenteditable 兼容性补丁,这反而是更省时间、更少出错的起点。


















