模型和模式
# 编辑器
编辑器有几种不同的类型。虽然它们在视觉上看起来不同,但它们在幕后是相似的,并且包含两个部分:
- 编辑引擎,
- 编辑 UI。
在本教程的本章和接下来的几章中,您将了解编辑引擎,它负责读取、维护和输出编辑器状态,以及所有在幕后为编辑器提供动力的其他内容。
稍后您还将了解编辑 UI,但现在,您只需要知道它就是用户看到的并与其交互的界面。
# 模型
编辑引擎中第一个也是最重要的部分是模型。模型是类似 HTML 的结构,它表示编辑器的内容。当调用editor.setData()
方法时,作为参数传递的 HTML 将被转换为模型。然后,当调用editor.getData()
方法时,模型将被转换回 HTML。
模型与 HTML 之间的一个主要区别是,在模型中,文本和元素都可以具有属性。
让我们看看模型与 HTML 相比如何。
Hello world!
# 模式
您不能将任何您想要的内容放在文档模型中。至少在您更新模式之前是这样。模式定义了哪些内容是允许的以及在何处允许、哪些属性允许用于某些节点、哪些内容是不允许的,等等。
模式决定了诸如给定元素是否可以包含在块引用中,或者是否在选定的内容上启用粗体按钮等内容。
# 扩展模型以支持文本高亮
有了这些信息,我们该如何添加对高亮的支持?我们需要处理两件事:
- 我们需要在模型中以某种方式跟踪文本的哪些部分被高亮显示。
- 由于 HTML 使用
<mark>
元素来进行高亮显示,因此我们希望能够将其转换为模型并从模型转换回来。
# 扩展模式
正如我们之前所学到的,模型中的文本节点可以具有属性。我们还看到,斜体、粗体和下划线文本不像 HTML 中那样使用元素,而是使用文本属性。由于高亮显示的工作方式与这三种文本样式相同,因此让我们采用相同的路径。
让我们扩展 $text
节点以允许一个名为 highlight
的新属性。将以下代码添加到 src/plugin.js
中 Highlight
函数的末尾:
editor.model.schema.extend( '$text', {
allowAttributes: 'highlight'
} );
# 转换 HTML 元素
现在我们能够将 highlight
属性添加到文本部分了,让我们使 <mark>
HTML 元素能够转换为模型的 highlight
属性,反之亦然。将以下代码添加到 src/plugin.js
中 Highlight
函数的末尾:
editor.conversion.attributeToElement( {
model: 'highlight',
view: 'mark'
} );
为什么当我们想要将 <mark>
HTML 元素转换为 highlight
模型 属性时,该方法被命名为 attributeToElement()
?难道不应该反过来吗?
对于编辑器来说,模型是最重要的状态,而 HTML 只是输入和输出。从它的角度来看,角色是相反的 - 它具有 highlight
属性,它对应于 HTML 中的 <mark>
元素。当我们深入研究下一章中的数据转换时,您将看到这种模式重复出现。
# 测试更改
让我们测试一下我们的更改。在浏览器中打开控制台,并运行以下代码:
editor.setData( '<p>Hello <mark>world</mark>!</p>' );
如果一切顺利,world
这个词应该在编辑器中被高亮显示。
# CKEditor 检查器
让我们检查一下编辑器以验证模式和模型。打开 src/main.js
文件,并安装CKEditor 检查器。
// Import inspector.
import CKEditorInspector from '@ckeditor/ckeditor5-inspector';
// Add this at the bottom of the file to inspect the editor.
CKEditorInspector.attach(editor);
当页面刷新后,您应该看到 CKEditor 的调试面板。转到 Schema
选项卡,然后单击 $text
元素。在右侧的 Allowed Attributes
部分下,您应该看到 highlight:true
。
转到 Model
选项卡,并在控制台中重新运行以下代码:
editor.setData( '<p>Hello <mark>world</mark>!</p>' );
注意模型是如何改变的,以及 highlight
属性是如何附加到 "world"
字符串上的。
您还可以转到 View
选项卡,查看 highlight
属性是如何转换为 <mark>
元素的。
我们将在插件开发的下一阶段使用此工具。
# 下一步
如果您想了解更多有关编辑引擎的信息,请参阅编辑引擎 文档。
否则,请转到下一章,您将了解有关数据转换的更多信息以及当我们调用 attributeToElement()
方法时真正发生了什么。
我们每天都在努力使我们的文档保持完整。您是否发现过时信息?是否缺少某些内容?请通过我们的问题跟踪器 报告。
随着 42.0.0 版本的发布,我们重新编写了大部分文档以反映新的导入路径和功能。感谢您的反馈,帮助我们确保文档的准确性和完整性。