CKEditor5——模型理解(二:Node)

上一节我们理解了基本的CK5的模型基本信息,今天我们来学习一些模型的API。

节点说明

首先,需要理解的就是模型的节点。在这一点上,CK5的模型节点和dom的节点有点类似,也有一些不同。我会在文章中一一介绍。

节点是模型树的基本结构。它是模型中不同节点类型的一种抽象。

这里需要指出的一点是:如果一个节点从模型树中分离出来,你可以使用它的 API 来操作它。但是,非常重要的是,已经附加到模型树的节点只能通过 Writer API 进行更改。

如果您修改文档根目录中的节点,使用节点方法(如 _insertChild 或 _setAttribute)完成的更改不会记录到文档的历史操作中,这可能对某些功能造成困扰。

节点属性说明

我们来看看节点有哪些基本属性:

1、index,节点索引

就是这个节点在父元素中的索引。举个例子

<heading>
	<paragraph><$text>abc</$text></paragraph> 	//paragraph-1
	<paragraph><$text>def</$text></paragraph>	//paragraph-2
	<paragraph></paragraph>					    //paragraph-3
</heading>

在上面的模型中,我们在 <heading>中定义了两个paragraph节点paragraph-1paragraph-2 在这种情况下paragraph-1的index值就是0而paragraph-2的index值就是1。还有一点需要注意就是index是相对于父元素,因此我们知道节点应该有另一个属性parent。

2、parent,节点父元素

节点的父元素不难理解哈,需要注意的是节点的父元素有两种类型Element | DocumentFragment

3、root,根元素

节点的根元素就是节点最顶层的祖先元素,如果节点没有在文档树结构上是,此时的root就是一个DocumentFragment

4、previousSibling,节点的前一个元素

这个属性用于快速访问节点的前一个兄弟元素

5、nextSubling,节点的后一个元素

这个属性用于快速访问节点的后一个兄弟元素

6、offsetSize,节点所占据的偏移大小。

这个属性需要仔细说说,还是用上面的例子举例,paragraph-3是元素节点类型,它里面没有文本元素,那么它的offsetSize就是1,也就是占据一个偏移大小,而paragraph-2中的文本节点<$text>def</$text>它就要占据3个偏移大小。

paragraph-2的offsetSize就是它的子元素的offsetSize之和。这里有没有问题?欢迎大家讨论?

7、startOffset,节点的起始偏移值

这个值用于指示节点的开始位置相对于父元素的偏移,它等于它之前所有兄弟的 offsetSize 的总和。

8、endOffset,节点的结束偏移值

这个值用于指示节点的结束位置相对于父元素的偏移,它等于该节点的起始偏移量和节点偏移量大小之和。

为了说明上面的问题,我新建了一个模型如上图所示,我们看看第一个paragraph的startOffset,endOffset以及offsetSize

可以看到对于元素节点类型,它的startOffset和endOffset的值是0和1,而它有一个maxOffset值来记录它的子元素占据的offsetSize。

对于文本节点类型,它的startOffset和endOffset的值是0和4,offsetSize是4,它有一个path,实际上就是节点的起始位置,有了这个位置,我们可以结合其他API来进行相应的创建位置,创建范围,创建选择区等等。这个我们以后再讨论。

节点方法说明

节点有很多判断属性和获取属性的方法,比较简单,我们就不详细说明啦。我们只看看几个比较重要且关键的方法。

1、getAncestors() ,返回祖先元素

这个方法用于返回节点的祖先元素数组

2、getCommonAncestor(node) ,返回共同祖先元素

这个方法用于返回参数节点和调用节点共同祖先元素。

3、getPath() ,获取节点的路径

这是一个最重要的方法,它返回节点的路径。路径是一个数组,其中包含此节点的连续祖先的起始偏移量,从根开始,一直到此节点的起始偏移量。该路径可用于创建 Position 实例。

为了说明问题,我还是举一个例子

const abc = new Text( 'abc' );
const foo = new Text( 'foo' );
const h1 = new Element( 'h1', null, new Text( 'header' ) );
const p = new Element( 'p', null, [ abc, foo ] );
const div = new Element( 'div', null, [ h1, p ] );
//generate dom
<div>
	<h1>header</h1>
	<p>abcfoo</p>
</div>
foo.getPath(); // Returns [ 1, 3 ]. `foo` is in `p` which is in `div`. `p` starts at offset 1, while `foo` at 3.
h1.getPath(); // Returns [ 0 ].
div.getPath(); // Returns [].

通过上面的例子,我想大家应该很容易理解这个方法了吧

4、is( type ) → Boolean

检查节点是否是指定类型。此方法在处理未知类型的模型对象时很有用。例如,一个函数可能返回一个 DocumentFragment 或一个可以是文本节点或元素的节点。此方法可用于检查返回的对象类型。还需要注意的是

这个方法会被它的很多子类覆盖重写

 

总结

今天我们对模型的节点这个类的属性和方法进行了基本的分析和介绍,特别是几个重点属性和方法,如果掌握清楚啦,对未来的CK学习将会有很大的帮助作用。欢迎各位留言讨论。

版权声明:著作权归作者所有。

相关推荐

理解Java 9的open module(公开模块)

模块化是Java 9新增的一个很重要且影响代码结构的特性。分类根据外部代码在编译时和运行时对模块的访问权限不同分为:常规模块(normal module)和公开模块(open module)。编译时访问比较容易理解,即代码能否显式直接使用模块里的类型,没有权限访问,编译时报错。在运行时访问模块代码是指使用Java里的Core Reflection 

理解RxJava里Observables的相关类型

Observable — Operator — ObserverObservable,可观察者,它就好像扬声器一样,做一些处理后发射出一些值。Operator,操作符,它就像翻译员那样将数据从一种形式翻译/修改为另一种形式。Observer,观察者,它获得那些由可观察者发射出来的或者有操作符转译的值。它们的关系如图: RxJava可观察类型在RxJava的可观察类型如下

RxJs——Subject理解二

上一节我们对subject有了初步理解,今天我们继续学习subjectReplaySubject介绍这个ReplaySubject之前,我们说下一种使用场景1、我们创建一个subject2、在应用的某个地方,我们向subject推送值,但此时没有订阅3、在某个时点,有第一个观察者开始订阅4、我们期望观察者能接收之前主题推送的值(可能是全部值或者时其中一个)5、实际上啥都没发生,因为主题不能存储记忆

CKEditor5——模型理解(一)

我们知道,CK5实现了一个MVC的架构,从今天开始,我们一步一步深入学习模型,视图,以及模型和视图之间的转换。今天我们开始模型的学习。首先,我们看模型的定义:The model is implemented by a DOM-like tree structure of elements and text nodes.模型由两类节点构成,分别是元素节点和文本节点,模型是一种类Dom树结构。我们知道

RxJs——错误处理(二)

从前文我们知道,错误处理有两种方式,一种是重新抛出一个错误,另一个是提供一个默认的回调值。今天我们介绍错误处理的另一种方式,先来看看重试。重试策略有一点需要记住,一旦流出现了错误,我们不能恢复它。但是没有什么能阻碍我们订阅其派生类对应的Observable,并且创建一个新的流。这种策略的工作原理是:1、我们将获取输入Observable并且订阅它,这将创建一个新的流。2、如果流没有出错,我们将在输

CKEditor5——模型理解(三:Element Text)

在上一节,我们学习了CK5中模型节点Node的API,今天我们学习另一个常用的API:Element。元素节点说明element表示模型的元素节点类型,它包含一个拥有名称和子节点的节点类型,继承自Node类。元素属性说明1、name,元素的名称举个例子哈,段落的名称是paragraph,代码块的名称是codeBlock等等。2、childCount, 子元素的数目这里指的是此元素节点包含的子元素的

CKEditor5——模型理解(五:Position, Range, Selection)

今天我们继续学习CK5中模型的一些知识,主要包括:Position, Range, Selection首先,我们需要知道:position表示模型树中的一个位置。模型的位置有两部分组成:root,path。即位置由其根和该根中的路径表示。位置基于偏移量,而不是索引。这意味着两个文本节点 foo 和 bar 之间的位置偏移为 3,而不是 1。由于模型中的位置由位置根和位置路径表示,因此可以创建不存在

CKEditor5——模型理解(六:Range)

上一节我们主要介绍了模型中的Position这个关键的类,今天我们开始学习Range这个类。简单来说的话,如果Position表示一个点的话,那么Range是不是可以理解为一条线段呢?这个线段有一个startPostion,endPosition以及线段的长度等属性,我们暂且这么认为,那么我们可以看看Range官方的文档。从文档中看到,Range类有五个属性:Range属性start:Positi

CKEditor5——模型理解(七:Selection)

昨天我们学习了Range的一些API使用,今天我们看看另一个重要的类Selection的API:Selection的作用是记录鼠标在文档上的选择区域,如果是单个用户在编辑一份文档的时候,选择应该就是一个Range,如果是多个用户在编辑一份文档的时候,那么选择的区域就应该是多个range。因此,我大胆的猜测,Selection中应该有Range数组。我们来看看吧。Selection属性anchor