สร้างบล็อกขั้นตอนที่กำหนดเอง

การสร้างการบล็อกกระบวนการที่กำหนดเองกำหนดให้คุณต้องดำเนินการดังนี้

  1. ติดตั้ง @blockly/block-shareable-procedures ปลั๊กอิน ตามที่อธิบายไว้ในกระบวนการใช้ หน้าเว็บ
  2. ใช้ระบบการเรียงอันดับ JSON ตามที่อธิบายไว้ในภาพรวม

เพิ่มโมเดลข้อมูลลงในพื้นที่ทำงาน

ทั้งคำจำกัดความของโพรเซสและการบล็อกตัวเรียกกระบวนการอ้างอิงข้อมูลสนับสนุน โมเดลที่กำหนดลายเซ็นของกระบวนการ (ชื่อ พารามิเตอร์ และ ผลลัพธ์) ซึ่งจะช่วยเพิ่มความยืดหยุ่นในการออกแบบแอปพลิเคชัน (เช่น คุณสามารถอนุญาตให้กำหนดกระบวนการในพื้นที่ทำงานเดียว และมีการอ้างอิงใน อีกรายการ)

ซึ่งหมายความว่าคุณจะต้องเพิ่มโมเดลข้อมูลกระบวนการลงในพื้นที่ทำงาน เพื่อให้การบล็อกทำงาน ซึ่งทำได้หลายวิธี (เช่น กําหนดเอง 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.

    // 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...
  }
};

เพิ่มการเรียงลำดับแบบกำหนดเอง

การทำให้เป็นอนุกรมสำหรับบล็อกกระบวนการต้องทำ 2 สิ่งแยกกัน

  1. เมื่อโหลดจาก JSON บล็อกของคุณจะต้องดึงการอ้างอิงไปยัง สนับสนุนโมเดลข้อมูล เนื่องจากบล็อกและโมเดลถูกเรียงลำดับแยกกัน
  2. เมื่อคัดลอกและวางบล็อกกระบวนการ การบล็อกจะต้องเรียงลำดับ สถานะทั้งหมดของโมเดลกระบวนการ เพื่อให้ทำซ้ำได้

ทั้ง 2 ขั้นตอนนี้ได้รับการจัดการผ่าน 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);