Contents

富文本总结(一):前置知识

编辑器技术阶段划分

Level 0

代表产品:UEditor、TinyMCE、CKEditor1-4

特点:

  1. 依赖了浏览器原生的 contenteditable API 来实现编辑。
  2. document.execCommand API 为基础,封装一些语法糖进行内容操作。
  3. 视图即数据。

优点:

  1. 技术门槛低。
  2. 没有组合输入问题。

缺点:

  1. 兼容性差,相同操作在不同浏览器上会有不同实现,需要做各种兼容处理。
  2. 输出富文本内容是 HTML ,不利于管理数据。
  3. 扩展复杂的富文本很困难。
  4. 无法实现协同编辑。

Level 1

代表产品:Quill、Draft.js、Slate、ProseMirror

为了解决contentEditable的不可靠,主流L1编辑器的做法是:

  1. 通过contenteditable依赖浏览器原生的编辑能力,通过事件监听、DOM 变更进行输入内容判断。

  2. 由编辑器提供的指令集,对内容进行操作。不再依赖 document.execCommand

  3. 视图和数据分离,由编辑器抽象的数据模型来描述视图层。

  4. 由编辑器控制内容解析,视图渲染解析后的DOM元素。

优点:

  • 减少 document.execCommand的一些不确定性问题。
  • 可以支持多人协同。

缺点:

  1. 引入一些组合输入问题。例如中文输入法问题,不同浏览器的事件存在差异。
  2. 会有性能问题。
  3. 有些编辑器的数据模型是扁平化,不支持嵌套。扩展复杂的嵌套内容很困难。
编辑器 类型 数据方式 数据结构 特点 缺点
Quill 应用 Delta 线性结构
Prosemirror 应用 JSON+Schemas(范式) 树形结构 新概念和 API 比较多,有着高昂的学习上手成本
Draft.js 框架 线性结构 基于React实现的组件,其他框架难以使用。
Slate 框架 JSON 树结构 1. 视图层与内核分离,官方提供React视图层,可以基于内核实现Vue、Angular框架的渲染层。2. 插件作为一等公民,扩展性很好。 1. 底层重构多次,目前版本可能还不稳定。

数据结构扁平化,带来的好处就是没有层级,复杂度低,例如:

  1. 性能更好。
  2. 选区更容易计算。
  3. 节点的操作更容易,不需要考虑子节点

关于类型:

应用:提供了开箱即用的编辑器,集成了很多常用功能,例如变色,加粗,图片上传等,缺点是扩展性稍差。

框架:只提供基础的编辑功能,其他功能都需要自行实现。一般会通过插件的形式,扩展性较好。

Level 2

特点:

  1. 抛弃 contenteditable 、 document.execCommand 操作内容,全部改为自己实现。
  2. 脱离DOM,基于Canvas实现。

优点:

  1. 不存在兼容问题,可以保持一致性。
  2. 协同性

缺点:

  1. 开发量巨大,需要从0实现编辑器的所有功能,例如光标、选区、输入、渲染,a11y。

产品:Google Docs、飞书文档、腾讯文档等

contentEditable

浏览器所提供的<textarea /><input /> 都只允许用户输入「纯文本」,无法对内容中的文本加一些样式,例如变色,加粗。而HTML本身就是一个富文本,可以看下例子,

/images/image-20220822152653281.png

<div style="display: flex; height: 100vh; align-items: center; justify-content: center;">
    <span style="color: blue;font-size: 20px;">bhwa233</span>
    want
    <span style="color: red;font-weight: bold;">fat</span>
</div>

而如果能在页面上编辑HTML就实现了富文本编辑器的能力,浏览器自身相应了响应的能力:

  1. 元素的 contentEditable 属性,允许节点内容被编辑。
  2. document.execCommand方法,允许对元素的操作,包括加粗、改背景、绑定链接、复制、剪切等。

但是存在兼容性问题,即不同浏览器对其编辑的行为实现不一致,导致在不同浏览器显示的效果出现很大差异。

详细:https://zhuanlan.zhihu.com/p/298101935

参考文章:

富文本编辑器 L1 能力调研记录

开源富文本编辑器技术的演进(2020 1024)