序列化是保存工作区的状态,以便稍后能够将其重新加载到工作区。这包括将要保存的任何代码块、变量或插件的状态序列化。您可以将需要保存的所有数据转换为基于文本的格式,以方便存储,然后在以后将这些数据加载回功能齐全的工作区。
Blockly 为这些数据提供了两种格式:JSON 和 XML。我们建议对新项目使用 JSON 系统,并鼓励使用 XML 升级的旧项目升级。XML 系统采用旧版保存格式。但不会移除,但不会收到新功能。
JSON 系统
JSON 序列化系统由多个序列化器组成。有一些适用于块和变量的内置序列化器,您也可以注册其他序列化器。每个序列化器负责对特定插件或系统的状态进行序列化和反序列化。
保存和加载
工作区
您可以通过对 workspaces
命名空间调用 save
和 load
方法,对整个工作区的状态进行序列化或反序列化。
const state = Blockly.serialization.workspaces.save(myWorkspace);
Blockly.serialization.workspaces.load(state, myWorkspace);
这些调用会序列化或反序列化在工作区中注册的所有系统(由序列化器表示)。
单个方块
您可以通过对 blocks
命名空间调用 save
和 append
方法,对各个块进行序列化或反序列化。
const blockJson = Blockly.serialization.blocks.save(myBlock);
const duplicateBlock =
Blockly.serialization.blocks.append(blockJson, myWorkspace);
个别系统
您可以通过构造关联的序列化器并调用其 save
和 load
方法,对各个系统(例如块、变量、插件等)进行序列化或反序列化。
// Saves only the variables information for the workspace.
const serializer = new Blockly.serialization.variables.VariableSerializer();
const state = serializer.save(myWorkspace);
serializer.load(state, myWorkspace);
反序列化顺序
JSON 系统具有明确的反序列化顺序,因此可以更轻松地防止在保存过程中出现重复状态。
调用 Blockly.serialization.workspaces.load
时,系统会按优先级为序列化器指定反序列化状态。序列化器部分对此进行了进一步说明,其用途是允许序列化器依赖于来自其他系统的状态。
内置序列化器的反序列化顺序如下:
- 变量是反序列化的。
- 代码块会反序列化。各个堆栈/顶级块按任意顺序反序列化。
- 类型反序列化。这会触发块的 init 方法、扩展程序中的混音,等等。
- 属性反序列化。这包括可应用于任何块的属性。例如:x、y、合拢、已停用、数据等。
- Extra 状态会进行反序列化。如需了解详情,请参阅扩展程序和变更器文档。
- 代码块会连接到其父级组件(如果存在)。
- 图标是反序列化的。各个图标按任意顺序反序列化。
- 字段会反序列化。各个字段以任意顺序进行反序列化。
- 输入块反序列化。这包括连接到值输入和语句输入的块。各个输入按任意顺序进行反序列化。
- 后续代码块会反序列化。
何时保存额外状态
对于块,如果顺序中较低部分依赖于顺序中的较高部分,则应复制相应数据并将其添加到额外状态。
例如,如果您有一个字段仅在下一个块连接的情况下存在,则应该将有关下一个块的信息添加到额外状态,以便在将字段状态反序列化之前,可以将该字段添加到您的块中。
但是,如果输入仅在某个字段具有特定值时存在,则无需向额外状态添加有关该字段的信息。这是因为字段状态将首先进行反序列化,届时,您可以将输入添加到块中。添加输入通常由验证器触发。
请注意,有关复制状态的规则还应考虑屏蔽堆栈、图标、字段和输入块按任意顺序反序列化。例如,有一个字段 B 仅在另一个字段 A 具有特定值时存在,您应将 A 的相关信息添加到额外状态,以防 B 在 A 之前反序列化。
块钩子
如需了解如何向块中添加额外的序列化,请参阅扩展和变更器文档。
字段钩子
如需了解如何对字段进行序列化,请参阅自定义字段文档。
序列化器钩子
在 JSON 系统中,您可以注册序列化器,这些序列化器用于对某些状态进行序列化和反序列化。Blockly 的内置序列化器负责序列化有关块和变量的信息,但如果您想序列化其他信息,则需要添加自己的序列化器。例如,默认情况下,JSON 系统不会序列化工作区级注释。如果要将其序列化,您需要注册额外的序列化器。
其他序列化器通常用于对插件的状态进行序列化和反序列化。
Blockly.serialization.registry.register(
'workspace-comments', // Name
{
save: saveFn, // Save function
load: loadFn, // Load function
clear: clearFn, // Clear function
priority: 10, // Priority
});
注册序列化器时,您必须提供以下各项:
- 序列化器的名称,数据也会保存在其中。
- 一个函数,用于
save
与序列化器关联的插件/系统的状态。 - 用于对状态执行
clear
的函数。 - 用于对状态执行
load
的函数。 priority
,用于确定反序列化顺序。序列化器的优先级基于内置优先级
调用 Blockly.serialization.workspaces.save
时,系统会调用每个序列化器的 save
函数,并将其数据添加到最终 JSON 输出中:
{
"blocks": { ... },
"workspaceComments": [ // Provided by workspace-comments serializer
{
"x": 239,
"y": 31,
"text": "Add 2 + 2"
},
// etc...
]
}
调用 Blockly.serialization.workspaces.load
时,每个序列化器都会按优先级触发。优先级值较高的序列化器会在优先级值较低的序列化器之前触发。
触发序列化器时,会出现以下两种情况:
- 系统会调用所提供的
clear
函数。这样可以确保在加载更多状态之前,插件/系统的状态是干净的。例如,workspace-comments 序列化器会从工作区中移除所有现有注释。 - 系统会调用所提供的
load
函数。
XML 系统
利用 XML 系统,您可以将工作区序列化为 XML 节点。这是 Blockly 的原始序列化系统。它现在已采用冰箱模式,这意味着它不会接收新功能。因此,建议您尽可能使用 JSON 系统。
API
如需了解 XML 系统的 API,请参阅参考文档。
块钩子
如需了解如何向块中添加额外的序列化,请参阅扩展和变更器文档。
字段钩子
如需了解如何对字段进行序列化,请参阅自定义字段文档。
选择 JSON 或 XML
我们建议您使用 JSON 序列化器而非 XML 序列化器。通过 JSON 系统,您可以将工作区的状态序列化为 JavaScript 对象。这样做的好处在于:
- JSON 易于压缩或转换为其他格式。
- 以编程方式使用 JSON 非常容易。
- JSON 可以轻松扩展和附加数据。
此外,XML 系统将不再接收更新,并且与 JSON 序列化器相比,已经缺少功能。例如,您可以注册自己的 JSON 序列化器,以便轻松保存和加载其他数据,例如您已添加的插件或自定义项的数据。在 XML 系统中不可能做到这一点。
如果您之前使用过 XML 序列化,请参阅迁移指南,了解如何升级。