หากต้องการสร้างการบล็อกขั้นตอนที่กำหนดเอง คุณต้องทำดังนี้
- ติดตั้งปลั๊กอิน @blockly/block-shareable-procedures ตามที่อธิบายไว้ในหน้าการใช้กระบวนการ
- ใช้ระบบการทำให้เป็นอนุกรม JSON ตามที่อธิบายไว้ในหน้าภาพรวม
เพิ่มโมเดลข้อมูลไปยังพื้นที่ทำงาน
ทั้งการกำหนดขั้นตอนและการบล็อกการเรียกใช้กระบวนการจะอ้างอิงโมเดลข้อมูลสำรองซึ่งจะกำหนดลายเซ็นของกระบวนการ (ชื่อ พารามิเตอร์ และ Return) วิธีนี้ช่วยให้คุณออกแบบแอปพลิเคชันได้อย่างยืดหยุ่นมากขึ้น (เช่น คุณอนุญาตให้กำหนดกระบวนการทำงานในพื้นที่ทำงานหนึ่งและอ้างอิงในอีกพื้นที่ทำงานหนึ่งได้)
ซึ่งหมายความว่าคุณจะต้องเพิ่มโมเดลข้อมูลกระบวนการลงในพื้นที่ทำงานเพื่อให้การบล็อกทำงานได้ ซึ่งทำได้หลายวิธี (เช่น UI ที่กำหนดเอง)
@blockly/block-shareable-procedures นี้โดยให้บล็อกการกำหนดขั้นตอนสร้างโมเดลข้อมูลสนับสนุนแบบไดนามิกเมื่อมีการสร้างอินสแตนซ์ข้อมูลลงในพื้นที่ทำงาน หากต้องการติดตั้งใช้งานด้วยตนเอง ให้สร้างโมเดลใน 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.
this.workpace.getProcedureMap().delete(model.getId());
}
}
แสดงข้อมูลเกี่ยวกับการบล็อก
การกำหนดกระบวนการและการบล็อกการเรียกใช้กระบวนการจำเป็นต้องใช้เมธอด getProcedureModel
, isProcedureDef
และ getVarModels
นี่คือฮุกที่โค้ด 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...
}
};
เพิ่มการทำให้เป็นอนุกรมที่กำหนดเอง
การทำให้เป็นอนุกรมสำหรับบล็อกกระบวนการต้องทำ 2 สิ่งแยกกัน
- เมื่อโหลดจาก JSON บล็อกจะต้องดึงการอ้างอิงไปยังโมเดลข้อมูลสนับสนุน เนื่องจากบล็อกและโมเดลต่างๆ มีการเรียงลำดับแยกกัน
- เมื่อคัดลอกและวางบล็อกกระบวนการ บล็อกดังกล่าวจะต้องทำให้สถานะของโมเดลกระบวนการเป็นอนุกรม เพื่อที่จะจำลอง/ทำซ้ำได้
ทั้ง 2 อย่างนี้จะได้รับการจัดการผ่าน saveExtraState
และ loadExtraState
ขอย้ำอีกครั้งว่าระบบจะรองรับการบล็อกขั้นตอนที่กำหนดเองเฉพาะเมื่อใช้ระบบการเรียงลำดับ JSON เท่านั้น เราจึงต้องกำหนดฮุกอนุกรม JSON เท่านั้น
import {
ObservableProcedureModel,
ObservableParameterModel,
isProcedureBlock
} from '@blockly/block-shareable-procedures';
Blockly.Blocks['my_procedure_def'] = {
saveExtraState() {
return {
'procedureId': this.model.getId(),
// These properties are only necessary for pasting.
'name': this.model.getName(),
'parameters': this.model.getParameters().map((p) => {
return {name: p.getName(), p.getId()};
}),
'returnTypes': this.model.getReturnTypes(),
};
},
loadExtraState(state) {
const id = state['procedureId']
const map = this.workspace.getProcedureMap();
// Grab a reference to the existing procedure model.
if (this.model.getId() != id && map.has(id) &&
(this.isInsertionMarker || this.noBlockHasClaimedModel_(id))) {
// Delete the 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']);
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']));
}
},
// We don't want to reference a model that some other procedure definition
// is already referencing.
noBlockHasClaimedModel_(procedureId) {
const model =
this.workspace.getProcedureMap().get(procedureId);
return this.workspace.getAllBlocks(false).every(
(block) =>
!isProcedureBlock(block) ||
!block.isProcedureDef() ||
block.getProcedureModel() !== model);
},
};
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 เพื่อแก้ไขโมเดลกระบวนการ ได้แก่ การใช้การเปลี่ยนแปลง (ซึ่งเป็นวิธีที่ใช้บล็อกกระบวนการในตัว) ช่องรูปภาพที่มีแฮนเดิลการคลิก หรือสิ่งที่อยู่ภายนอก Blockly โดยสิ้นเชิง เป็นต้น
เพิ่มบล็อกในกล่องเครื่องมือ
หมวดหมู่ขั้นตอนแบบไดนามิกที่มีในตัวของ 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);