連線檢查

連線檢查會限制哪些連線 (以及因此而產生的區塊) 可以彼此連線。

連線檢查可用於模擬類型。舉例來說,下列三個區塊並未連結,因為它們代表的程式碼會傳回不同的類型:

空白清單區塊連結至平方根區塊,再連結至大寫區塊

您可以使用連線檢查功能,防止這些區塊連線。這可為使用者提供即時意見回饋,並避免許多簡單的錯誤。

運作方式

每個連線都可以與「連線檢查」相關聯,這是一個可為空的字串陣列。

兩個連線可以連結,如果:

  1. 這些是相容的類型 (例如連結至輸入端的輸出端)。
  2. 兩者至少有一個共同的連線檢查字串。

舉例來說,下列兩個檢查的連線可以連結,因為它們共用 'apple' 字串:

['apple', 'ball', 'cat']
['apple', 'bear', 'caterpillar']

不過,這兩個檢查項目的連線無法連結,因為它們沒有共用任何字串:

['apple', 'ball', 'cat']
['ape', 'bear', 'caterpillar']

還有另一個特殊情況。如果任一陣列為 null,則兩個連線也可以連結。這樣一來,您就能定義可連結至任何項目的連線。

null
['ape', 'bear', 'caterpillar]

範例

如需使用連線檢查功能的範例清單,請參閱連線檢查藍圖

設定檢查

根據預設,所有連線都會進行 null 連線檢查,也就是說,連線可以連上任何項目。連線檢查必須手動指派。

您為連線指派連線檢查的方式,取決於您是使用 JSON 區塊定義還是 JavaScript 區塊定義。

JSON

對於頂層連線,您可以直接將檢查作業指派給定義連線的屬性。您指派的值可以是 null、字串 (成為連線檢查中的唯一項目),或是字串陣列。

{
  'type': 'custom_value_block',

  'output': 'a connection check entry',
},
{
  'type': 'custom_statement_block',

  'nextStatement': null, // null check
  'previousStatement': ['four', 'connection', 'check', 'entries']
}

針對輸入內容,您可以將檢查項目指派給輸入定義的 check 屬性。如果不存在 check 屬性,系統會將檢查視為 null。您指派的值可以是字串,也可以是字串陣列。

{
  'type': 'custom_block',
  'message0': '%1 %2',

  'args0': [
    {
      'type': 'input_value',
      'check': 'a connection check entry' // Accepts custom_value_block
    },
    {
      'type': 'input_statement',
      'check': ['two', 'entries'] // Accepts custom_statement_block
    }
  ]
}

JavaScript

對於頂層連線,您可以直接將檢查作業傳遞至定義連線的方法。如果您未傳遞值,系統會將檢查視為 null。您傳遞的值可以是字串 (這會成為連線檢查中的唯一項目),或是字串陣列。

Blockly.Blocks['custom_value_block'] = {
  init: function() {
    this.setOutput(true, 'a connection check entry');
  }
};
Blockly.Blocks['custom_statement_block'] = {
  init: function() {
    this.setNextStatement(true); // null check
    this.setPreviousStatement(true, ['four', 'connection', 'check', 'entries']);
  }
};

針對輸入內容,您可以在定義輸入內容後,將檢查作業傳遞至 setCheck 方法。如果未呼叫 setCheck 方法,系統會將檢查視為 null。您傳遞的值可以是字串,也可以是字串陣列。

Blockly.Blocks['custom_block'] = {
  init: function() {
    this.appendValueInput('NAME')
        .setCheck('a connection check entry'); // Accepts custom_value_block
    this.appendStatementInput('NAME')
        .setCheck(['two', 'entries']); // Accepts custom_statement_block
  }
};

內建的檢查字串

內建區塊的連線檢查值為 'Array''Boolean''Colour''Number''String'。如果您希望區塊與內建區塊互通,可以使用這些值讓區塊相容。

限制

這個系統相當穩健,可解決許多用途,但仍有幾項限制。

限制更大的脈絡

這個系統本身不支援限制「更大脈絡」中允許連線的情況。舉例來說,您無法指出 break 區塊只能存在於 loop 區塊中。連線檢查系統只會考慮即時連線的兩個連線。

您可以使用事件系統來監聽區塊移動事件,並檢查區塊是否放錯位置,以支援這項功能。

Blockly.Blocks['custom_block'] = {
  init: function() { }

  onchange: function(e) {
    if (this.workspace.isDragging()) return;
    if (e.type !== Blockly.Events.BlockMove) return;
    if (!this.getSurroundLoop()) this.outputConnection.disconnect();
  }

  loopTypes: new Set(); // Your valid *block types* (not connection checks).

  getSurroundLoop: function () {
    let block = this.getSurroundParent();
    do {
      if (loopTypes.has(block.type)) return block;
      block = block.getSurroundParent();
    } while (block);
    return null;
  },
}

一般類型

這個系統本身不支援定義泛型類型。舉例來說,您無法建立「Identity」區塊,因為該區塊會「傳回」任何輸入內容。

您可以部分支援這項功能,方法是主動變更區塊輸出內容的連線檢查,以符合輸入內容。您可以使用事件系統監聽區塊移動事件。

Blockly.Blocks['custom_block'] = {
  init: function() { }

  onchange: function(e) {
    if (e.type !== Blockly.Events.BlockMove) return;
    this.setOutput(
        true, this.getInputTargetBlock()?.outputConnection.getCheck());
  }
}

但如果連結的區塊也是泛型,則這項做法無法正常運作。目前沒有任何可行的解決方法。

連線檢查工具

如果這個系統不適用於您的用途,您也可以建立自訂連線檢查器,變更連線檢查的比較方式。

舉例來說,如果您想建立更進階的系統來處理此系統的部分限制,可以建立自訂連線檢查器。