序列化

序列化是保存工作区的状态,以便稍后将其重新加载到工作区。这包括序列化您要保存的任何块、变量或插件状态。您可以将需要保存的所有数据转换为基于文本的格式以便于存储,之后再将这些数据加载到功能齐全的工作区中。

Blockly 为此类数据提供了两种格式:JSON 和 XML。我们建议为新项目使用 JSON 系统,并鼓励使用 XML 的旧项目进行升级。XML 系统是旧版保存格式。我们不会移除该版本,但不会为其添加新功能。

JSON 系统

JSON 序列化系统由多个序列化器组成。块和变量有内置序列化器,您还可以注册其他序列化器。每个序列化器都负责序列化和反序列化特定插件或系统的状态。

保存和加载

工作区

您可以对 workspaces 命名空间调用 saveload 方法,对整个工作区的状态进行序列化或反序列化。

const state = Blockly.serialization.workspaces.save(myWorkspace);
Blockly.serialization.workspaces.load(state, myWorkspace);

这些调用会对在工作区中注册的所有单个系统(由序列化器表示)进行序列化或反序列化。

单个分块

您可以通过对 blocks 命名空间调用 saveappend 方法,对各个块进行序列化或反序列化。

const blockJson = Blockly.serialization.blocks.save(myBlock);
const duplicateBlock =
    Blockly.serialization.blocks.append(blockJson, myWorkspace);

单个系统

您可以通过构建关联的序列化程序并调用其 saveload 方法,对各个系统(例如块、变量、插件等)进行序列化或反序列化。

// 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 时,系统会按优先级为序列化程序提供要反序列化的数据状态。序列化器部分对此进行了进一步说明,其目的是允许序列化器依赖于其他系统的状态。

对内置序列化程序进行反序列化的顺序如下:

  1. 变量模型会进行反序列化。
  2. 过程模型已反序列化。
  3. 代码块会反序列化。各个顶级块会按任意顺序进行反序列化。
    1. 类型已反序列化。这会构建块、触发其 init 方法,并混入扩展程序。
    2. 属性会进行反序列化。这包括可应用于任何块的属性。例如:x、y、collapsed、disabled 和 data。
    3. 额外状态会反序列化。如需了解详情,请参阅扩展程序和修饰符文档。
    4. 代码块已连接到其父级(如果有)。
    5. 图标已进行反序列化。各个图标会以任意顺序进行反序列化。
    6. 字段会进行反序列化。各个字段会以任意顺序进行反序列化。
    7. 输入块会反序列化。这包括连接到值输入和语句输入的代码块。各个输入会以任意顺序进行反序列化。
    8. 后续块会反序列化。

何时保存额外状态

对于块,如果顺序中较低的内容依赖于较高顺序的内容,则应复制该数据并将其添加到额外状态中。

例如,如果您的字段仅在下一个块连接时才存在,则应将有关下一个块的信息添加到 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 时,系统会按优先级顺序触发每个序列化器。优先级值越高的序列化器会先于优先级值较低的序列化器触发。

触发序列化器时,会发生以下两种情况:

  1. 系统会调用提供的 clear 函数。这可确保在加载更多状态之前,插件/系统的状态是干净的。例如,工作区评论序列化器会从工作区中移除所有现有评论。
  2. 系统会调用提供的 load 函数。

XML 系统

借助 XML 系统,您可以将工作区序列化为 XML 节点。这是 Blockly 的原始序列化系统。该 SDK 现已被搁置,这意味着它不会再收到新功能。因此,我们建议您尽可能使用 JSON 系统。

API

如需了解 XML 系统的 API,请参阅参考文档

块钩子

如需了解如何向块添加额外的序列化,请参阅扩展程序和修饰符文档。

字段钩子

如需了解如何对字段进行序列化,请参阅自定义字段文档。

在 JSON 和 XML 之间进行选择

我们建议使用 JSON 序列化器而不是 XML。JSON 系统允许您将工作区的状态序列化为 JavaScript 对象。这样做有以下好处:

  1. JSON 易于压缩或转换为其他格式。
  2. JSON 易于以编程方式处理。
  3. JSON 易于扩展和附加数据。

此外,XML 系统将不再收到更新,并且与 JSON 序列化器相比,它已经缺少一些功能。例如,您可以注册自己的 JSON 序列化器,以便轻松保存和加载其他数据,例如您添加的插件或自定义项的数据。在 XML 系统中无法实现此操作。

如果您之前使用的是 XML 序列化,请参阅迁移指南,了解如何升级。