富文本编辑器 Quill 入坑指南
Quill 是一款 API 驱动、功能强大的现代富文本编辑器。它具有易于拓展、各平台表现一致性等优点。Quill 官方 1.0 版本于 2016 年 9 月发布,目前在 Github 上有 33.1k Star。
基本概念
Module
Quill 是以可拓展性和定制化为理念进行设计的。它尽可能简洁地实现了的编辑器的核心功能,并暴露接口供开发者进行定制化开发。这些核心功能就是通过 Module 来组织管理的。主要的 Module 有这些:
- Toolbar,它的主要功能是让用户方便快捷地对文本进行格式化。我们可以更改该模块的配置,控制操作栏按钮的数量、排列顺序、展现形式等等
- Keyboard,它的主要功能是为键盘事件进行定制化的控制。例如,当我们需要对选中的文字进行加粗,可以点击操作栏加粗按钮实现,也可以直接通过快捷键 command+b 来达到目的。
- History,它主要是提供编辑器的 undo 和 redo 的功能。通过配置项,我们还可以设置多少秒内的操作合并为一个快照记录。
- Clipboard,它主要用于处理编辑器和外部应用之间的复制、粘贴等操作。值得注意的是,Quill 编辑器对文本格式有一定要求,粘贴到富文本的内容可能会被稍作处理。
- Syntax,该模块用于代码块的语法高亮。Quill 编辑器的语法高亮需要借助 highlight.js 来进行词法分析。
Parchment
Parchment 是 Quill 的文档模型,你可以把它类比为 HTML 中的 DOM 树。正如 DOM 树是由 DOM 节点构成,Parchment 则是由 Blots 构成。Quill 默认提供了几种常见的 Blots 例如:Block Blot、Inline Blot、Embed Blot。为了便于理解,你可以将其类比为 HTML 中的内联元素和块状元素。为了满足不同的格式化需求,Quill 允许我们自定义 Blot。现在我们来实现一个使文字变成斜体的功能:
let Inline = Quill.import('blots/inline');
class ItalicBlot extends Inline { }
ItalicBlot.blotName = 'italic';
ItalicBlot.tagName = 'em';
Quill.register(ItalicBlot);
const quill = new Quill('#editor');
quill.formatText(0, 4, 'italic', true);
我们在实现一个自定义的 Blot 的时候,并不需要完全从零开始,可以继承自 Quill 默认提供的基础 Blot。一个最简单的 Blot 至少有两个最基本的静态属性,blotName 和 tagName。其中 blotName 在格式化的时候作为名字传入,而 tagName 则是创建的 HTML 元素的标签名,在本文示例中使用 em 标签实现斜体效果。
Delta
Delta 是一种用来描述文本内容和内容编辑的简单、极富表现力的格式。它是基于 JOSN 格式,易于阅读和解析。Delta 可以用来描述任何富文本文档对象,并且它没有 HTML 的复杂性和语义不明确性。我们通过一个示例来看看 Delta 结构是什么样子的。假若文本编辑器的内容为:“ Gandalf the Grey ”,如你所见,第一个单词 “Gandalf” 是有粗体效果的,最后一个单词 “Grey” 则是斜体效果。那么代表文本编辑器内容的 Delta 则是如下格式:
Delta = {
ops: [
{ insert: 'Gandalf', attributes: { bold: true } },
{ insert: ' the ' },
{ insert: 'Grey', attributes: { italic: true } }
}
那如果我们想把编辑器内容由 “ Gandalf the Grey ” 改为 “ Gandalf theWhite”又该如何操作呢?答案很简单,保持前面 12 个字符不动,插入单词“White”并使文字变蓝,删除接下来的四个字符即可。在 Quill 编辑器中调用如下代码即可实现:
const delta = new Delta().retain(12)
.insert('White', { color: '#00F' })
.delete(4);
quill.updateContents(delta)
亮点归纳
1. 支持定制化和具备高拓展性。前面我们说过,Quill 的核心功能是通过 Module 来组织。Module 内部允许用户自行配置,比如 Toolbar,可以配置操作栏显示哪些按钮。Module 层面也支持配置,如果你不想要编辑器的操作栏,只需要不添加该模块即可。假若 Quill 提供的操作栏不能符合你的需求,你可以定义自己的 Toolbar Module 进行替换内置的模块。此外,如果你想在更多地介入文本的编辑转换过程,Quill 也提供了便捷的 API 供你使用:
// 可以监听编辑器的内容变化
quill.on('text-change', function(delta, oldDelta, source) {