升級自訂欄位

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 已變更,但如果您選擇不變更,欄位大多仍可正常運作。

SERIALIZABLE

如要進一步瞭解 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 開發人員論壇發布升級相關問題。

如果您確定問題出在 Blockly 核心,也可以在 Blockly GitHub 上發布問題。如要發布問題,請填寫所有必要資訊。