CKEditor系列之数据模型

243 阅读4分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第2天,点击查看活动详情

概览

相对于早期的富文本编辑器,CKEditor更进一步,提供了一套数据转换机制,通过数据模型来进行视图的渲染,用户的操作直接作用数据模型,而不再是直接进行dom的操作。

数据模型转化势必是双向的:Model转化为View、View转化为Model。而在CKEditor5中,用来映射视图元素的模型元素称为Schema,而对于模型元素和视图元素之间相互转化过程我们称为Conversion

  • Conversion:分为两种:downcastupcast。其中,对于downcast可以细分为两种:Data downcastEditing downcast,分别用于处理创建和编辑过程的转化。

  • Schema:,包含 rootroot、block 、$text 分别指代根节点、块元素、普通文本。

视图转换为模型(upcast)

CKEditor5提供了向上转化的通道——upcast。每次进行初始化的时候,都会通过upcast将数据转换为模型。

upcast转化的过程中,定义了 UpcastWriter 来操作视图树,约定了 elementToElement、elementToAttribute、attributeToAttribute 三种转化规则来处理Schema,将视图元素转化为模型元素。

视图元素划分为 ContainerElement、UIElement、Emptyelement、Aattributeelement、EditableElement、Text 等几种类型,分别对应不同功能的容器元素、UI元素、空元素、属性元素、可编辑元素、文本。

1. elementToElement

elementToElement实现将视图元素(div、p)转换为相应的模型元素。

    editor.conversion.for( 'upcast' ).elementToElement( {
	view: 'p',
	model: 'example'
    } );

这是一个将视图元素div转化为模型元素example的例子,至于example的具体属性定义在example的Schema中:

2. elementToAttribute

elementToAttribute实现将内联文本格式视图元素(strong、i等)转换为模型元素上的属性。

    editor.conversion
        .for( 'upcast' )
        .elementToAttribute( {
            view: 'strong',
            model: 'bold'
        } );

这是一个将加粗文本转换为paragraph模型元素上的bold属性的示例:

3. attributeToAttribute

attributeToAttributen实现将视图元素的属性(src、href等)转换到模型元素上的属性。

    editor.conversion
        .for( 'upcast' )
        .attributeToAttribute( {
            view: 'src'
            model: 'source'
        } );

这是一个将视图元素img的src属性转换为模型元素image的source属性的示例:

模型转化为视图(downcast)

CKEditor也提供了向下转化的通道——downcast,用来将模型转换为视图。大家进行视图编辑的时候,都会直接应用于模型,然后通过downcast转化为视图,间接来更新视图内容,而不是想象中的直接操作dom;当通过editor.getData() 获取编辑器内容的时候,触发的也是downcast。

在视图转换的过程中,我们通过定义了DowncastWriter(不同于UpcatWriter)来创建视图元素,约定了elementToElement、attributeToElement、attributeToAttribute、elementToStructure规则来转化Schema,并提供了几种创建视图容器的方法createContainerElement、createUIElement、createEmptyElement、createAttributeElement、createEditableElement、createText(与upcase中处理的视图元素相对应);downcase中一种额外的方法createSlot来创建可插入内容的容器元素。

1. elementToElement

elementToElement实现将模型元素转换为视图元素(div、p等),这应该是最常用的转换规则了。

    editor.conversion
        .for( 'downcast' )
        .elementToElement( {
            model: 'paragraph',
            view: 'p'
        } );

这是一个将模型元素paragraph转化为视图元素p的例子,至于paragraph的具体属性定义在paragraph的Schema中:

2. attributeToElement

elementToAttribute实现将模型元素上的属性转换为内联文本格式视图元素(strong、i等)。

    editor.conversion
        .for( 'downcast' )
        .attributeToElement( {
            model: 'bold',
            view: 'strong'
        } );

这是一个将paragraph模型元素上的bold属性转换为加粗文本示例:

3. attributeToAttribute

attributeToAttributen实现将视图元素的属性(src、href等)转换到模型元素上的属性。

    editor.conversion
        .for( 'downcast' )
        .attributeToAttribute( {
            model: 'source',
            view: 'src',
        } );

这是一个将模型元素image的source属性转换为视图元素img的src属性的示例:

4. elementToStructure

elementToStructure实现复杂的模型元素的转换,其余的转化方式跟upcast都存在相互对应的,唯有这个方法是downcast独有的。这种视图元素是由视图元素及其子元素组成的,需要跟createSlot组合使用来创建父容器。

    editor.conversion
        .for( 'downcast' ).elementToStructure( {
            model: 'container',
            view: ( modelElement, { writer } ) => {
                return writer.createContainerElement( 'div', { class: 'wrapper' }, [
                    writer.createContainerElement( 'div', { class: 'inner-wrapper' }, [
                        writer.createSlot()
                    ] )
                ] );
            }
        } );

这是一个将模型元素container转换为嵌套的容器元素的示例(其中,视图元素p是大家进行编辑的时候插入的):