什么是Quill?
Quill是一款由API驱动的强大的JavaScript富文本编辑器。它主要的优点是有良好的兼容性和可扩展性,支持市面上几乎所有的主流浏览器。
背景
最近在项目中用到了Quill富文本编辑器,所以有必要了解Quill的概念和用法。经过阅读Quill的官方文档以及该作者发布的文章,将了解到的相关知识做了整理。
安装
Quill
在使用Quill初始化编辑器之前,首先需要安装Quill。Quill的安装分为两种情况:如果项目中没有用到Webpack等前端编译打包工具,我们需要将Quill资源文件加载到html中。
<!-- 引入css文件 -->
<link href="https://cdn.quilljs.com/1.0.0/quill.snow.css" rel="stylesheet">
<!-- 自定义编辑器工具栏 -->
<div id="toolbar">
<button class="ql-bold">Bold</button>
<button class="ql-italic">Italic</button>
</div>
<!-- 创建编辑容器 -->
<div id="editor">
<p>Hello World!</p>
</div>
<!-- 引入js文件 -->
<script src="https://cdn.quilljs.com/1.0.0/quill.js"></script>
如果项目中使用了Webpack,则可以通过npm包管理工具安装Quill:
npm install quill -D
待安装完成后将Quill导入项目文件中:
import Quill from 'quill/core';
import Toolbar from 'quill/modules/toolbar';
import Snow from 'quill/themes/snow';
import Bold from 'quill/formats/bold';
import Italic from 'quill/formats/italic';
import Header from 'quill/formats/header';
Quill.register({
'modules/toolbar': Toolbar,
'themes/snow': Snow,
'formats/bold': Bold,
'formats/italic': Italic,
'formats/header': Header
});
export default Quill;
初始化
在Quill安装工作做好之后就可以初始化编辑器了:
var options = {
debug: 'info',
modules: {
toolbar: '#toolbar'
},
placeholder: 'Compose an epic...',
readOnly: true,
theme: 'snow'
};
var editor = new Quill('#editor', options);
Quill初始化时提供了一些配置项可供选择,options内容如下:
属性 | 类型 | 描述 | 默认值 |
---|---|---|---|
bounds | 可以设置为DOM元素或代表DOM元素的CSS选择器,用来包含编辑器的UI元素(比如tooltips等等),当前只考虑左右边界。d | document.body | |
debug | debug的快捷方式。注意,debug是一个静态方法并且可能影响当前页面内Quill编辑器实例。默认只显示警告和错误信息。 |
| warn | | formats | | 编辑器允许的格式列表白名单。完整的列表,请见Formats。 | | | modules | | 需要引入模块的集合及它们各自的选项。详情见See Modules。 | | | placeholder | | 当编辑器为空时显示的占位符文字。 | | | readOnly | | 是否将编辑器实例设置为只读模式 | false | | scrollingContainer | | 当默认的’ql-editor’元素已经被自定义CSS改变,可以设置为DOM元素或代表DOM元素的CSS选择器,指定有滚动条(overflow-y: auto)的容器。 | null | | strict | | 在semver的严格解释下,一些改进或修改被要求一个大版本的bump。它们通过strict严格标志来防止对Quill版本号进行小的更改。 | true | | theme | | 使用主题的名称。这个内置的选项是”bubble”或”snow”。一个无效或错误的值将加载默认的最小化主题。注意,主题的样式表任需要手动包含 | |
Parchment
Parchment是抽象文档模型,是与DOM树相对应的树形结构,Parchment树由若干个Blot组成。Parchment为Quill提供了许多有用的功能。可以使用npm包管理器安装Parchment:
npm install parchment -D
Parchment安装完成后将Parchment导入到文件中使用:
import Parchment from 'parchment';
let Align = new Parchment.Attributor.Class('align', 'blot-align');
Parchment.register(Align);
let node = document.createElement('div');
Align.add(node, 'right');
console.log(node.outerHTML); // Will print <div class="blot-align-right"></div>
Delta
Delta是一个扁平数组,用于保存编辑器中的内容。Delta数组中的每一项表示一次操作,它的变化直接影响编辑器中的内容变化。可以对Delta进行添加、删除和保留操作。
const delta = new Delta([
{ insert: 'Gandalf', attributes: { bold: true } },
{ insert: ' the ' },
{ insert: 'Grey', attributes: { color: '#ccc' } }
]);
const death = new Delta().retain(12)
.delete(4)
.insert('White', { color: '#fff' });
Blot
Blot是Parchment文档的重要组成部分,用户可以通过操作Blot来实现对编辑器内容的修改,无需操作真实DOM。Blot是DOM Node对应物。Blot包含对应的结构、样式和内容。Blot对象拥有以下属性:
属性名称 | 描述 |
---|---|
parent | Blot父节点,若没有则为null |
prev | 上一个同级Blot,若没有则为null |
next | 下一个同级Blot,若没有则为null |
scroll | 顶级Blot |
domNode | 当前Blot对应的真实DOM节点 |
Blot.create
Blot类中存在静态方法create
,每个Blot的创建的过程中会调用creae
方法,在该方法中会返回创建后的真实DOM节点,但该节点此时并未插入文档。如果想要修改真实DOM节点的属性,可以在create
方法中修改。
import Block from 'quill/blots/block'
class MyBlock extends Block {
static create(initialValue) {
const node = super.create()
node.classList.add('my-class')
return node
}
}
用户通过复制粘贴创建的内容,会直接将剪切板中的html结构添加到编辑器中,不会通过
create
方法
构造函数
Blot通过domNode在构造函数中实例化。在构造函数中,可以增加比如事件绑定等操作。
import Block from 'quill/blots/block'
class MyBlock extends Block {
constructor(domNode) {
super(domNode)
this.addEvents(domNode)
}
static create(initialValue) {
const node = super.create()
node.classList.add('my-class')
return node
}
addEvents(domNode) {
domNode.addEventListener('click',()=>{
//...
})
}
}
注册Blot
添加完自定义Blot后,需要将该Blot注册到Quill中,这样才会被编辑器识别。
import Quill from 'quill';
import Block from 'quill/blots/block'
class MyBlock extends Block {
constructor(domNode) {
super(domNode)
this.addEvents(domNode)
}
static create(initialValue) {
const node = super.create()
node.classList.add('my-class')
return node
}
addEvents(domNode) {
domNode.addEventListener('click',()=>{
//...
})
}
}
MyBlock.className='my-block'
MyBlock.blotName='MyBlock'
MyBlock.tagName='div'
Quill.register(MyBlock)
创建Blot必须使用Parchment.create方法创建,使用new关键字实例化会影响到Blot生命周期正常工作
插入Blot
先使用Parchment.create
创建blot节点,再利用insertInto(parentBlot,refBlot)
方法可以将blot插入到父节Blot中。
const newBlot = Parchment.create("someBlotName", initialBlotValue);
const parentBlot = /* Get a reference to the desired parent Blot in some way */;
newBlot.insertInto(parentBlot);
除了上述,还可以使用
insertAt(index,name,value)
、insertBefore(childBlot,refBlot)
也可以插入Blot节点。
扩展
- vue-quill-editor
- quill-image-extend-module
- quill-image-resize-module
- quill-image-drop-module
- quill-better-table
- quilljs-table
总结
Quill是一款非常优秀的Javascript富文本编辑器,与其它富文本编辑器相比最大的区别是提供了例如Parchement
、Blot
、Delta
等抽象模型,使用户可以在不直接操作底层DOM基础上轻松修改编辑器内容。同时它的可扩展性也非常强,用户可以根据自己需要定制各个功能模块。