升级自定义字段

2019 年 7 月(版本 2.20190722)添加了更规范化的字段 API。它旨在尽可能向后兼容。也就是说,如果您在 2019 年 7 月之前创建了自定义字段,那么它很可能将继续有效。在决定是否需要升级自定义字段之前,您应仔细阅读危险区域部分,并对字段进行全面测试。

由于在 2019 年 7 月之前各字段之间缺乏标准化,因此开发者很难涵盖开发者可能需要进行的所有更改。本文档尽可能涵盖所有可能的更改,但如果本文档未涵盖您感兴趣的内容,请阅读获取升级帮助部分。

危险区域

危险区域是已知的 API 更改位置,这些字段可能会发生故障。

Blockly.Field.register

字段不再通过 Blockly.Field.register(); 注册。现在有一个 fieldRegistry 命名空间可以处理注册。

Blockly.Field.register('my_field_name', myFieldClass);

会变为:

Blockly.fieldRegistry.register('my_field_name', myFieldClass);

setText

Blockly 核心不再调用 setText 函数,因此,如果您的 setText 函数包含逻辑,则需要将其移至函数值处理套件、getText 函数和渲染函数(具体取决于您的 setText 函数具体执行的操作)。

CustomFields.UpgradeField.prototype.setText = function(newText) {
  // Do validation.
  if (typeof newText != 'string' || newText === this.text_) {
    return;
  }

  // Fire event.
  if (this.sourceBlock_ && Blockly.Events.isEnabled()) {
    Blockly.events.fire(new Blockly.Events.BlockChange(
        this.sourceBlock_, 'field', this.name, this.text_, newText
    ));
  }

  // Update text value.
  this.text_ = 'prefix' + newText;

  // Rerender.
  this.size_.width = 0;
};

会变为:

CustomFields.UpgradeField.prototype.doClassValidation_ = function(newValue) {
  if (typeof newValue != 'string') {
    return null;
  }
  return newValue;
};

CustomFields.UpgradeField.prototype.getText = function() {
  return  'prefix' + this.value_;
}

Blockly 会自动处理:

  • 检查新值是否与旧值不同。
  • 更新值。
  • 触发更改事件。
  • 重新渲染字段。

您需要处理:

推荐的升级是指字段 API 已更改的位置,但如果您选择不进行更改,您的字段很可能仍可正常运行。

可序列化

如需详细了解 EDITABLESERIALIZABLE 属性,请参阅可修改和可序列化的属性

CustomFields.UpgradeField.prototype.SERIALIZABLE = true;

以下警告可忽略,但您可以通过定义 SERIALIZABLE 属性来解决:

Detected an editable field that was not serializable. Please define
SERIALIZABLE property as true on all editable custom fields. Proceeding
with serialization.

上述警告表示 Blockly 认为您希望对字段进行序列化(因为 EDITABLE 属性为 true),但在您定义 SERIALIZABLE 属性之前无法确定。如果您选择不予处理,则一切将正常运行,并且您的字段将被序列化,但您会收到控制台警告。

size_.width

this.size_.width = 0;

会变为:

this.isDirty_ = true;

以下警告可忽略,但您可以通过设置 isDirty_ 属性(而非 size_.width 属性)来解决:

Deprecated use of setting size_.width to 0 to rerender a field. Set
field.isDirty_ to true instead.

上述警告表示 Blockly 检测到您在使用旧方法重新渲染字段,并希望您使用新方法。

如需详细了解 isDirty_ 属性,请参阅 isDirty_

init

init 函数已变为模板函数,以减少子类中的重复代码。

CustomFields.UpgradeField.prototype.init = function() {
  if (this.fieldGroup_) {
    // Already initialized once.
    return;
  }

  // Call superclass.
  CustomFields.UpgradeField.superClass_.init.call(this);

  // Create DOM elements.
  this.extraDom_ = Blockly.utils.dom.createSvgElement('image',
      {
        'height': '10px',
        'width': '10px'
      });
  this.extraDom_.setAttributeNS('http://www.w3.org/1999/xlink',
      'xlink:href', 'image.svg');
  this.extraDom_.style.cursor = 'pointer';
  this.fieldGroup_.appendChild(this.extraDom_);

  // Bind events.
  this.mouseOverWrapper_ =
    Blockly.browserEvents.bind(
        this.getClickTarget_(), 'mouseover', this, this.onMouseOver_);
  this.mouseOutWrapper_ =
    Blockly.browserEvents.bind(
        this.getClickTarget_(), 'mouseout', this, this.onMouseOut_);

  // Render.
  this.setValue(this.getValue());
};

会变为:

CustomFields.UpgradeField.prototype.initView = function() {
  CustomFields.UpgradeField.superClass_.initView.call(this);

  this.extraDom_ = Blockly.utils.dom.createSvgElement('image',
      {
        'height': '10px',
        'width': '10px'
      });
  this.extraDom_.setAttributeNS('http://www.w3.org/1999/xlink',
      'xlink:href', 'image.svg');
  this.extraDom_.style.cursor = 'pointer';
  this.fieldGroup_.appendChild(this.extraDom_);
};

CustomFields.UpgradeField.prototype.bindEvents_ = function() {
  CustomFields.UpgradeField.superClass_.bindEvents_.call(this);

  this.mouseOverWrapper_ =
    Blockly.bindEvent_(
        this.getClickTarget_(), 'mouseover', this, this.onMouseOver_);
  this.mouseOutWrapper_ =
    Blockly.bindEvent_(
        this.getClickTarget_(), 'mouseout', this, this.onMouseOut_);
};

这意味着,blockly 现在会自动处理:

  • 检查该字段是否已初始化。
  • 创建 fieldGroup_
  • 渲染字段。
  • 绑定提示并显示编辑器事件。

您需要处理:

onMouseDown_

CustomFields.UpgradeField.prototype.onMouseDown_ = function(e) {
  // ...
};

会变为:

CustomFields.UpgradeField.prototype.showEditor_ = function() {
  // ...
}

我们建议您替换 showEditor_ 函数来处理鼠标点击,而不是替换 onMouseDown_ 函数,因为后者允许输入通过手势系统传递。

如需详细了解编辑器,请参阅编辑器

setValue

setValue 函数现在是一个模板函数,用于减少子类中的重复代码。如果 setValue 函数包含逻辑,请考虑对其进行重构,以适应值处理中所述的值处理路径。

text_

我们建议您切勿直接访问或更新字段的 text_ 属性,请改为使用 getText 函数访问字段的用户可读文本,并使用 setValue 函数更新字段的存储值。

如需详细了解字段的值与字段文本,请参阅字段详解

获取升级帮助

需要提供的内容

寻求帮助时,最好询问具体问题:

不建议:“此字段有什么问题?”

不建议的做法:“请帮我升级此字段。”

推荐:“字段文本未正确更新。”

向为您提供帮助的人提供资源也是很有必要的。这些文件应该易于他人使用。

不推荐:

  • 代码图片。
  • 代码不完整。

推荐:

  • 以文本格式完整填写字段代码。
  • 不良字段行为的 GIF 图片。
  • 重现不良字段行为的步骤。
  • 您要升级的 blockly 的版本。

发帖位置

blockly 开发者论坛上发布升级问题。

如果您确定问题是与块级核心有关,还可以在块式 GitHub 上发布问题。如果您决定发布问题,请填写所需的所有信息。