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

时间:2023-05-12 17:42:33

上一节我们理解了基本的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,节点的结束偏移值

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

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

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

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

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

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

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

对于文本节点类型,它的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学习将会有很大的帮助作用。欢迎各位留言讨论。