简介: quill 是一个跨平台的功能强大的富文本编辑器。开发者可以通过简单的API来控制编辑器的内容。
Parchment:Parchment是Quill的文档模型。它是DOM树的并行树结构,并提供了对内容编辑器(如Quill)有用的功能。Parchment树由Blob组成
Blot:Blot是Parchment文档的组成部分,它是quilljs中最重要的抽象。有了Blot,可以让用户对编辑器中的内容进行操作,而无需对DOM进行直接操作
Delta: 是一个扁平的JSON数组,用于保存(描述)编辑器中的内容数据。Delta中的每一项代表了一次操作,它的变化会直接影响到编辑器中内容的变化
核心组件:
Parchment:是指定义和管理文本格式的模块。
Blot:则代表了Quill中的基本构建单元,可以理解为一个可编辑区域内的一段内容。
Delta:是Quill使用的一种数据格式,用于表示富文本编辑器中的内容和样式。
三者关系
在Quill富文本编辑器中,Parchment用于定义和管理文本格式(如字体、颜色等),
而Blot则代表了编辑器中的基本构建单元,
在Delta数据格式中被使用来表示这些内容和样式
Delta 的数据格式:
{
ops: [
{ insert: 'Gandalf', attributes: { bold: true } },
{ insert: ' the ' },
{ insert: 'Grey', attributes: { color: '#cccccc' } },
{
insert: {image: 'https://quilljs.com/assets/images/icon.png'},
attributes: {
link: 'https://quilljs.com'
}
},
{ insert: 'The Two Towers' },
{ insert: '\n', attributes: { header: 1 } },
{ insert: 'Aragorn sped on up the hill.\n' }
]
}
操作函数:insert,delete,retain
文档函数:concat,diff,eachline,invert
Utility: filter,forEach,length,partition,reduce,slice
转换函数: compose,transform,transformPosition
Blots:
domNode: Node;
static tagName: 'div' ; html 标签
static className:'' ; 生成html 代码中的class
static blotName: 'block' ;
static allowedChildren :[] ; 允许的的子级标签,
static defaultChild: Registry.BlotConstructor;
children: LinkedList<Blot>;
update(mutations: MutationRecord[], context: { [key: string]: any });
//Blot发生变化时会被调用,参数mutation的target是blot.domNode。在同一次更新循环中,所有blots收到的sharedContext是相同的。
optimize(context: { [key: string]: any }): void;
//更新循环完成后会被调用,避免在optimize方法中改变document的length和value
value(): any; // 返回的值
static formats(domNode: Node);
format(format: name, value: any);
formats(): Object;
wrap(name: string, value?: any): Parent;
wrap(wrapper: Parent): Parent;
deleteAt(index: number, length: number): void;
formatAt(index: number, length: number, name: string, value: any): void;
insertAt(index: number, value: string, def?: any): void;
ShadowBlot 中
static requiredContainer: 定义该Blot需要被哪一个容器Blot包裹。当该Blot被创建完成后,会执行到ShadowBlot类中的optimize方法,其主要逻辑就是:检查该Blot的requiredContainer是否被设置,并且该Blot的父Blot不是requiredContainer设置的Blot类的实例,调用wrap方法(wrap的作用就是创建容器Blot实例,插入的该Blot的父级中,然后将该Blot插入到容器中)。
quill中的内置Blot都继承自ShadowBlot。 每个blot都拥有以下这些引用属性
.parent—父级blot,包含当前blot。若当前blot是顶级blot,则为null。
.prev—上一个同级blot, 与当前blot拥有同一个parent, 若当前blot为第一个child,则为null。
.next—下一个同级blot, 与当前blot拥有同一个parent, 若当前blot为最后一个child,则为null。
.scroll—顶级blot,后面会提供更多关于scroll blot的信息。
.domNode—当前blot的DOM结构,该blot在DOM树中的实际结构。
生命周期:
static create(initialValue):
用于根据初始值创建DOM Node。这里也非常适合在node上设置一些与Blot实例无关的初始属性。该函数会返回新创建的DOM Node,但并未插入文档中
create()并不是任何时候都会在blot实例化前执行,例如:当用户通过 复制/粘贴 创建blot时,blot的创建会直接接受来自剪切板的HTML结构,从而跳过create方法。
constructor(domNode): 构造函数,通过domNode实例化blot。在这里可以做一些通常在class的构造函数中做的事情,比如:事件绑定,缓存引用等。
static register(): 注册
开发一个嵌套组件基本思路流程(table 为例):
1: 先定义 table,theader,tobody,tr,td,th 这几个Blot,
在optimize 中判断是否帮定了上级,如果绑定则调用warp()
if (
this.statics.requiredContainer &&
!(this.parent instanceof this.statics.requiredContainer)
) {
this.wrap(this.statics.requiredContainer.blotName,{
row: rowId,
colspan,
rowspan
})
}
2: 配置嵌套关系:
tableBlot.allowedChildren = [tbodyBlot,theaderBlot]
tbodyBlot.requiredContainer = tableBlot
theaderBlot.requiredContainer = tableBlot
tbodyBlot.allowedChildren = [trBlot]
trBlot.requiredContainer = tbodyBlot
trBlot.allowedChildren = [thBlot,tdBlot]
thBlot.requiredContainer = trBlot
tdBlot.requiredContainer = trBlot
相关文献地址:
https://github.com/quilljs/parchment/
https://github.com/quilljs/delta
https://juejin.cn/post/6844903838982340622
https://juejin.cn/post/6844903844749508621