title: "实体与撤销/重做" post_status: publish comment_status: open taxonomy: category: - gutenberg-docs post_tag: - Architecture - Explanations - Repos
实体与撤销/重做
无论是文章编辑器还是站点编辑器,WordPress 编辑器操作的都是我们称为实体记录的对象。这些对象代表文章、页面、用户、分类项、模板等数据。它们存储在数据库中,并由编辑器进行操作。每个编辑器可以同时获取、编辑和保存多个实体记录。
例如,在站点编辑器中打开页面时:
- 您可以编辑页面本身的属性(标题、内容等)
- 您可以编辑页面模板的属性(模板内容、设计等)
- 您可以编辑模板使用的模板部件属性(页眉、页脚等)
编辑器会跟踪所有这些修改,并协调所有已修改记录的保存操作。这些功能在 @wordpress/core-data 包中实现。
编辑实体
要编辑实体,首先需要获取并将其加载到 core-data 存储中。例如,以下代码将 ID 为 1 的文章加载到存储中。(实体是文章,文章 1 是实体记录)。
wp.data.select( 'core' ).getEntityRecord( 'postType', 'post', 1 );
实体加载后,即可进行编辑。例如,以下代码将文章的标题设置为 "Hello World"。对于每个获取的实体记录,core-data 存储会跟踪以下内容:
- "持久化"记录: 从后端获取时记录的最终状态。
- "编辑"列表: 记录的一个或多个属性的未保存本地修改。
该包还提供了一组操作来操作获取的实体记录。
要编辑实体记录,可以调用 editEntityRecord,它接受实体类型、实体 ID 和新的实体记录作为参数。以下示例将 ID 为 1 的文章标题设置为 "Hello World"。
wp.data.dispatch( 'core' ).editEntityRecord( 'postType', 'post', 1, { title: 'Hello World' } );
编辑实体记录后,可以保存它。以下代码保存 ID 为 1 的文章。
wp.data.dispatch( 'core' ).saveEditedEntityRecord( 'postType', 'post', 1 );
撤销/重做
由于 WordPress 编辑器允许同时编辑多个实体记录,core-data 包会在一个公共的撤销/重做堆栈中跟踪所有已获取和编辑的实体记录。撤销/重做堆栈中的每个步骤都包含一个"编辑"列表,这些编辑在调用 undo 或 redo 操作时应同时被撤销或重做。
为了能够正确执行撤销和重做操作,编辑列表中的每次修改都包含以下信息:
- 实体类型和名称: core-data 中的每个实体由 (kind, name) 对标识。这对应于被修改实体的标识符。
- 实体记录 ID: 被修改记录的 ID。
- 属性: 被修改属性的名称。
- 从: 属性的先前值(用于执行撤销操作)。
- 到: 属性的新值(用于执行重做操作)。
例如,假设用户编辑了一篇文章的标题,然后修改了文章别名,接着修改了与该文章一起使用的可重用块的标题。以下信息将存储在撤销/重做堆栈中:
[ { kind: 'postType', name: 'post', id: 1, property: 'title', from: '', to: 'Hello World' } ][ { kind: 'postType', name: 'post', id: 1, property: 'slug', from: 'Previous slug', to: 'This is the slug of the hello world post' } ][ { kind: 'postType', name: 'wp_block', id: 2, property: 'title', from: 'Reusable Block', to: 'Awesome Reusable Block' } ]
存储库还会跟踪一个指向当前"撤销/重做"步骤的"指针"。默认情况下,指针始终指向堆栈中的最后一项。当用户执行撤销或重做操作时,此指针会更新。
缓存更改
撤销/重做核心行为还支持我们称之为"缓存修改"的功能。这些修改不会立即存储在撤销/重做堆栈中。例如,当用户在文本字段中开始输入时,字段的值会在存储中被修改,但这个修改直到用户移动到下一个单词或经过几毫秒后才会存储在撤销/重做堆栈中。这样做是为了避免为用户输入的每个字符都创建一个新的撤销/重做步骤。
缓存更改被保留在撤销/重做堆栈之外的所谓修改"缓存"中,这些修改只有在我们显式调用 __unstableCreateUndoLevel 或下一个修改不是缓存修改时才会存储在撤销/重做堆栈中。
默认情况下,所有对 editEntityRecord 的调用都被视为"非缓存"的,除非传递了 isCached 选项为 true。示例:
wp.data.dispatch( 'core' ).editEntityRecord( 'postType', 'post', 1, { title: 'Hello World' }, { isCached: true } );