变量

变量是重要的编程概念。Blockly 支持动态类型化语言(例如 Python 和 JavaScript),只需稍加处理,您便可添加信息来支持强类型化语言(或静态类型化语言),例如 Java 或 C。

如需详细了解动态类型语言与静态类型语言,请参阅数据类型简介:静态、动态、强类型和弱类型

Blockly 提供变量字段,这些字段是动态下拉框,用于显示用户提供的变量名称。以下是一个示例。

一个变量字段,其中包含一个下拉菜单,可用于选择变量、更改当前变量的名称或删除当前变量。

默认情况下,Blockly 允许将任何类型分配给变量,并且 Blockly 提供的所有生成器都适用于动态类型语言。如果您使用的是类型化语言,可以按以下步骤配置 Blockly 以支持该语言:

无类型变量块

用于访问和操控变量的最基本代码块是 getter 和 setter 代码块。我们来了解一下 Blockly 提供的 getter 和 setter 块。

JSON

// Block for variable getter.
{
  "type": "variables_get",
  "message0": "%1",
  "args0": [
    {    // Beginning of the field variable dropdown
      "type": "field_variable",
      "name": "VAR",    // Static name of the field
      "variable": "%{BKY_VARIABLES_DEFAULT_NAME}"    // Given at runtime
    }    // End of the field variable dropdown
  ],
  "output": null,    // Null means the return value can be of any type
  ...
},

// Block for variable setter.
{
  "type": "variables_set",
  "message0": "%{BKY_VARIABLES_SET}",
  "args0": [
    {
      "type": "field_variable",
      "name": "VAR",
      "variable": "%{BKY_VARIABLES_DEFAULT_NAME}"
    },
    {
      "type": "input_value",    // This expects an input of any type
      "name": "VALUE"
    }
  ],
  ...
}

JavaScript

// Block for variable getter.
Blockly.Blocks['variables_get'] = {
  init: function() {
    this.appendDummyInput()
      .appendField(new Blockly.FieldVariable("VAR_NAME"), "FIELD_NAME");
    this.setOutput(true, null);
    ...
  }
};

// Block for variable setter.
Blockly.Blocks['variables_set'] = {
  init: function() {
    this.appendValueInput("NAME")
        .setCheck(null)
        .appendField("set")
        .appendField(new Blockly.FieldVariable("VAR_NAME"), "FIELD_NAME")
        .appendField("to");
    this.setOutput(true, null);
    ...
  }
};

这会创建以下两个块:

变量 `foo` 的 getter 和 setter 块。

需要注意的一个重要细节是,通过将变量 getter 的“输出”设置为 null,返回值可以是任何类型。另请注意,变量设置器的输入未指定任何检查。因此,该变量可以设置为任何类型的值。

类型化变量块

您可以添加强制执行类型检查的 getter 和 setter。例如,如果您创建了一个类型为 "Panda" 的变量,则以下定义会创建具有相应类型的 getter 和 setter。

JSON

// Block for Panda variable getter.
{
  "type": "variables_get_panda",
  "message0": "%1",
  "args0": [
    {
      "type": "field_variable",
      "name": "VAR",
      "variable": "%{BKY_VARIABLES_DEFAULT_NAME}",
      "variableTypes": ["Panda"],    // Specifies what types to put in the dropdown
      "defaultType": "Panda"
    }
  ],
  "output": "Panda",    // Returns a value of "Panda"
  ...
},

 // Block for Panda variable setter.
{
  "type": "variables_set_panda",
  "message0": "%{BKY_VARIABLES_SET}",
  "args0": [
    {
      "type": "field_variable",
      "name": "VAR",
      "variable": "%{BKY_VARIABLES_DEFAULT_NAME}",
      "variableTypes": ["Panda"],
      "defaultType": "Panda"
    },
    {
      "type": "input_value",
      "name": "VALUE",
      "check": "Panda"    // Checks that the input value is of type "Panda"
    }
  ],
  "previousStatement": null,
  "nextStatement": null,
  ...
}

JavaScript

// Block for Panda variable getter.
Blockly.Blocks['variables_get_panda'] = {
  init: function() {
    this.appendDummyInput()
      .appendField(new Blockly.FieldVariable(
          "VAR_NAME", ['Panda'], 'Panda'), "FIELD_NAME");
    this.setOutput(true, 'Panda');
    ...
  }
};

// Block for Panda variable setter.
Blockly.Blocks['variables_set_panda'] = {
  init: function() {
    this.appendValueInput("NAME")
        .setCheck('Panda')
        .appendField("set")
        .appendField(new Blockly.FieldVariable(
            "VAR_NAME", null, ['Panda'], 'Panda'), "FIELD_NAME")
        .appendField("to");
        this.setPreviousStatement(true, null);
        this.setNextStatement(true, null);
    ...
  }
};

这会创建两种类型的块:getter 和 setter。其下拉菜单仅显示 "Panda" 类型的变量。它们的输入和输出仅接受类型为 "Panda" 的连接。相应字段的 defaultType 必须设置为 variableTypes 数组中的某个值。在提供 variableTypes 数组时不设置 defaultType 会导致抛出错误。

默认情况下,没有视觉指示器来告知用户正在使用哪种类型。区分变量类型的一种简单方法是使用颜色

向工具箱添加变量

为了让这种新类型的变量对用户有用,您需要添加一种创建和使用新变量的方法。

如果您还没有变量的动态类别,请创建一个新的动态类别

一个名为“变量”的打开类别,其中包含“创建变量”按钮。

将新的 getter 和 setter 添加到相应类别。

创建 `foo` 和 `bar` 变量后的同一类别。它包含“创建变量”按钮、set-variable-to 和 change-variable-by 代码块,以及 getter 代码块。

“创建变量”按钮

接下来,用户需要一种创建变量的方式。最简单的方法是使用“创建变量”按钮

创建按钮时,请确保回调调用

Blockly.Variables.createVariableButtonHandler(button.getTargetWorkspace(), null, 'panda');

系统会创建一个 "Panda" 类型的变量!

允许用户创建多种类型的变量的最简单方法是为每种类型提供一个“创建”按钮(例如“创建字符串变量”“创建数字变量”“创建 Panda 变量”)。

如果您有两到三种以上的变量类型,很快就会出现过多的按钮。在这种情况下,不妨考虑使用 @blockly/plugin-typed-variable-modal 显示一个弹出式窗口,用户可以从中选择所需的变量类型。

定义生成器

最后,您需要为新的变量块定义块代码生成器。您还可以使用 Workspace.getVariableMap().getAllVariables() 直接访问变量列表以获取所有类型的全部变量,或使用 Workspace.getVariableMap().getVariablesOfType() 获取特定类型的全部变量。