如要建立自訂程序區塊,您必須:
- 安裝 @blockly/block-shareable-procedures 外掛程式,方法如使用程序 頁面。
- 使用 JSON 序列化系統,如總覽 頁面。
將資料模型新增至工作區
程序定義和程序呼叫端都會封鎖參照備份資料 定義了程序簽章 (名稱、參數和 傳回)。讓您在設計應用程式 (例如 可讓您在單一工作區中定義程序,在 其他)。
這表示您需要將程序資料模型新增至工作區 才能使方塊正常運作做法有很多種 (例如自訂 UI)。
@blockly/block-shareable-procedures 執行這項操作
程序定義區塊會動態建立備份資料模型
這些 Pod 會在執行個體例項化至工作區中如要自行實作
在 init
中建立模型,然後在 destroy
中刪除模型。
import {ObservableProcedureModel} from '@blockly/block-shareable-procedures';
Blockly.Blocks['my_procedure_def'] = {
init: function() {
this.model = new ObservableProcedureModel('default name');
this.workspace.getProcedureMap().add(model);
// etc...
}
destroy: function() {
// (Optionally) Destroy the model when the definition block is deleted.
// Insertion markers reference the model of the original block.
if (this.isInsertionMarker()) return;
this.workpace.getProcedureMap().delete(model.getId());
}
}
傳回區塊相關資訊
您的程序定義和程序呼叫區塊,必須實作
getProcedureModel
、isProcedureDef
和 getVarModels
方法。這些是
以 hooks Blockly 程式碼取得程序區塊的相關資訊。
Blockly.Blocks['my_procedure_def'] = {
getProcedureModel() {
return this.model;
},
isProcedureDef() {
return true;
},
getVarModels() {
// If your procedure references variables
// then you should return those models here.
return [];
},
};
Blockly.Blocks['my_procedure_call'] = {
getProcedureModel() {
return this.model;
},
isProcedureDef() {
return false;
},
getVarModels() {
// If your procedure references variables
// then you should return those models here.
return [];
},
};
更新時觸發重新轉譯
您的程序定義和程序呼叫區塊,必須實作
doProcedureUpdate
方法。這是資料模型呼叫的重點
自行重新轉譯的程序區塊
Blockly.Blocks['my_procedure_def'] = {
doProcedureUpdate() {
this.setFieldValue('NAME', this.model.getName());
this.setFieldValue(
'PARAMS',
this.model.getParameters()
.map((p) => p.getName())
.join(','));
this.setFieldValue(
'RETURN', this.model.getReturnTypes().join(',');
}
};
Blockly.Blocks['my_procedure_call'] = {
doProcedureUpdate() {
// Similar to the def block above...
}
};
新增自訂序列化
程序區塊的序列化作業必須分開執行。
- 從 JSON 載入區塊時,您需要擷取區塊的參照 備份資料模型,因為區塊和模型會分別序列化。
- 複製及貼上程序區塊時,這個區塊必須序列化 完整狀態以便複製
這兩個項目都透過 saveExtraState
和 loadExtraState
進行處理。
再次提醒您,只有在使用 JSON 時,系統才會支援自訂程序區塊
因此,我們只需要定義 JSON 序列化掛鉤。
import {
ObservableProcedureModel,
ObservableParameterModel,
isProcedureBlock
} from '@blockly/block-shareable-procedures';
Blockly.Blocks['my_procedure_def'] = {
// When doFullSerialization is true, we should serialize the full state of
// the model.
saveExtraState(doFullSerialization) {
const state = Object.create(null);
state['procedureId']: this.model.getId();
if (doFullSerialization) {
state['name'] = this.model.getName();
state['parameters'] = this.model.getParameters().map((p) => {
return {name: p.getName(), p.getId()};
});
state['returnTypes'] = this.model.getReturnTypes();
// Flag for deserialization.
state['createNewModel'] = true;
}
return state;
},
loadExtraState(state) {
const id = state['procedureId']
const map = this.workspace.getProcedureMap();
if (map.has(id) && !state['createNewModel']) {
// Delete the existing model (created in init).
map.delete(this.model.getId());
// Grab a reference to the model we're supposed to reference.
this.model = map.get(id);
this.doProcedureUpdate();
return;
}
// There is no existing procedure model (we are likely pasting), so
// generate it from JSON.
this.model
.setName(state['name'])
.setReturnTypes(state['returnTypes']);
for (const [i, param] of state['parameters'].entries()) {
this.model.insertParameter(
i,
new ObservableParameterModel(
this.workspace, param['name'], param['id']));
}
this.doProcedureUpdate();
},
};
Blockly.Blocks['my_procedure_call'] = {
saveExtraState() {
return {
'procedureId': this.model.getId(),
};
},
loadExtraState(state) {
// Delete our existing model (created in init).
this.workspace.getProcedureMap().delete(model.getId());
// Grab a reference to the new model.
this.model = this.workspace.getProcedureMap()
.get(state['procedureId']);
if (this.model) this.doProcedureUpdate();
},
// Handle pasting after the procedure definition has been deleted.
onchange(event) {
if (event.type === Blockly.Events.BLOCK_CREATE &&
event.blockId === this.id) {
if(!this.model) { // Our procedure definition doesn't exist =(
this.dispose();
}
}
}
};
視需要修改程序模型
您也可以新增讓使用者修改程序模型的功能。撥號中
insertParameter
、deleteParameter
或setReturnTypes
方法
會自動觸發區塊重新算繪 (透過 doProcedureUpdate
)。
建立 UI 來修改程序模型的選項包括: mutator (也就是 內建程序模塊使用)、含有點擊處理常式的圖片欄位 這類物件
在工具箱中新增建塊
Blockly 的內建動態程序類別是 Blockly 內建的特定功能 程序區塊為了存取區塊,您必須先定義 您的自訂動態 類別,然後新增類別 這項工具新增至工具箱
const proceduresFlyoutCallback = function(workspace) {
const blockList = [];
blockList.push({
'kind': 'block',
'type': 'my_procedure_def',
});
for (const model of
workspace.getProcedureMap().getProcedures()) {
blockList.push({
'kind': 'block',
'type': 'my_procedure_call',
'extraState': {
'procedureId': model.getId(),
},
});
}
return blockList;
};
myWorkspace.registerToolboxCategoryCallback(
'MY_PROCEDURES', proceduresFlyoutCallback);