Contribute to this guide

guide向下转换 - 模型到视图

# 介绍

模型转换为视图的过程称为向下转换

Basic downcast conversion diagram.

每次需要将模型节点或属性转换为视图节点或属性时,都会发生向下转换过程。

编辑器引擎运行转换过程并使用插件注册的转换器。

# 注册转换器

要告诉引擎如何将特定的模型元素转换为视图元素,您需要使用editor.conversion.for( 'downcast' )方法注册一个向下转换转换器,列出应该在过程中转换的元素

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

上面的转换器将处理将每个<paragraph>模型元素转换为<p>视图元素。您可以在下面的代码片段中看到输入和输出。

这只是一个示例。事实上,段落支持已经由段落插件提供,因此您实际上不需要编写自己的<paragraph>元素到<p>元素转换。

您刚刚了解了elementToElement()向下转换转换辅助方法!更多助手在后面的章节中进行介绍。

# 向下转换管道

CKEditor 5 引擎使用两种不同的视图:数据视图编辑视图

数据视图用于生成编辑器输出。此过程由数据管道控制。

另一方面,编辑视图是您打开编辑器时看到的视图。这由编辑管道控制。

Downcast conversion pipelines diagram.

之前介绍的简单代码示例同时为这两个管道注册了一个转换器。这意味着<paragraph>模型元素将在数据视图编辑视图中都转换为<p>视图元素。

有时您可能想更改特定管道的转换器逻辑。例如,在编辑视图中,您可能希望在视图元素中添加一些额外的类。这种操作需要为这两个视图设置单独的转换器,与之前的示例不同,在之前的示例中,设置了一个通用的向下转换。

// dataDowncast for data pipeline
editor.conversion
    .for( 'dataDowncast' )
    .elementToElement( {
        model: 'paragraph',
        view: 'p'
    } );

// editingDowncast for editing pipeline
editor.conversion
    .for( 'editingDowncast' )
    .elementToElement( {
        model: 'paragraph',
        view: {
            name: 'p',
            classes: 'paragraph-in-editing-view'
        }
    } );

# 转换文本属性

您应该已经从关于模型的章节中知道,可以将属性应用于模型文本节点。

这种文本节点属性可以转换为视图元素。

为此,您可以使用attributeToElement()转换助手注册一个转换器

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

上面的转换器将处理将每个bold模型文本节点属性转换为<strong>视图元素,如下面的代码片段所示。

粗体文本

同样,这只是一个为了简单起见而给出的示例。粗体支持实际上由基本样式插件提供,因此您不必编写自己的粗体属性到强元素转换。

# 将元素转换为元素

与前面的示例类似,您可以使用elementToElement()转换助手<heading>模型元素转换为<h1>视图元素。实现此目的的代码如下所示

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

等同于

editor.conversion
    .for( 'downcast' )
    .elementToElement( {
        model: 'heading',
        view: ( modelElement, { writer } ) => {
            return writer.createContainerElement(
                'h1'
            );
        }
    } );

您之前已经了解到view属性可以是简单的字符串或对象。上面的示例表明,还可以定义一个自定义回调函数来返回创建的元素。这种转换的效果可以在下面的代码片段中观察到

<heading>元素在您可以设置视图中的标题级别时最有意义。

在上一章中,您已经了解到可以将属性应用于文本节点。也可以向元素添加属性,例如在以下示例中

editor.conversion
    .for( 'downcast' )
    .elementToElement( {
        model: {
            name: 'heading',
            attributes: [ 'level' ]
        },
        view: ( modelElement, { writer } ) => {
            return writer.createContainerElement(
                'h' + modelElement.getAttribute( 'level' )
            );
        }
    } );

从现在开始,每次级别属性更新时,整个<heading>元素将转换为<h[level]>元素(例如<h1><h2>等)。

您可以使用以下示例查看它的实际效果。使用下拉菜单更改模型中的标题级别,并查看视图元素如何通过转换器更新

同样,这只是一个示例。标题支持实际上由标题功能提供,因此您不必编写自己的<heading level="1"><h1>元素转换。

# 将元素转换为结构

有时您可能希望将一个单个模型元素转换为一个更复杂的视图结构,该结构包含一个具有子元素的单个视图元素

您可以使用elementToStructure()转换助手来实现此目的

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

上面的转换器将把所有<myElement>模型元素转换为<div class="wrapper"><div class="inner-wrapper"><p>...</p></div></div>结构,如下所示

示例结构

使用您自己的自定义模型元素需要首先在模式中定义它。

对于编辑器用户来说,与复杂结构交互的最佳方式是作为独立的实体,并保持完整,例如,在复制、粘贴和编辑时。CKEditor 5 通过小部件 API允许这样做。如果您想了解如何在elementToStructure()之上使用它,请务必查看实现块小部件教程。

# 进一步阅读

如果您想了解有关本指南中提到的向下转换助手的更多信息,我们已为您总结了这些助手,并附带完整的描述和示例。我们还建议您查看向上转换转换指南,并了解如何将编辑器输入的原始数据转换为活动的模型状态。