คำถามที่พบบ่อยคือวิธีแก้ไขคําจํากัดความของบล็อกที่มีอยู่ เช่น คุณอาจต้องการเพิ่มการตรวจสอบการเชื่อมต่อหรือเปลี่ยนช่องเป็นอินพุตค่า
โดยทั่วไปแล้ว คุณจะแก้ไขคําจํากัดความของบล็อกไม่ได้
วิธีแก้ไขคําจํากัดความที่มีอยู่
หากต้องการแก้ไขคําจํากัดความของประเภทบล็อกที่มีอยู่ ให้ทําดังนี้
- ทำสำเนาของคำจำกัดความที่มีอยู่ รวมถึงเครื่องมือสร้างโค้ดบล็อก
- แก้ไขข้อความและตั้งชื่อใหม่ให้ประเภท
- เพิ่มคําจํากัดความใหม่ลงใน
Blockly.Blocks
ทำไมฉันจึงแก้ไขคำจำกัดความที่มีอยู่โดยตรงไม่ได้
หากสงสัยว่าเหตุใดคุณจึงแก้ไขคําจํากัดความที่มีอยู่ไม่ได้ โปรดอ่านต่อ เราจะพิจารณาความเป็นไปได้บางอย่าง
แก้ไขคําจํากัดความที่มีอยู่โดยตรง
การแก้ไขคําจํากัดความของบล็อกที่มีอยู่โดยตรงทำได้ 2 วิธี ได้แก่ การแก้ไขโค้ดโดยตรง (Monkey Patching) และการแยกโค้ด เราขอแนะนำอย่างยิ่งว่าอย่าใช้ทั้ง 2 วิธีนี้ เนื่องจากคุณอาจเสี่ยงที่จะทำให้โค้ดที่ใช้โค้ดที่แก้ไขด้วย Monkey Patch หรือโค้ดที่แยกออกมาใช้งานไม่ได้ ทั้ง 2 เทคนิคยังทําให้ผสานรวมการอัปเดตและการแก้ไขข้อบกพร่องได้ยากด้วย ดูข้อมูลเพิ่มเติมได้ที่Monkeypatching เป็นอย่างไรและการแยก Blockly
กำหนดคลาสย่อยของคำจำกัดความที่มีอยู่
คุณอาจต้องการสร้างคลาสย่อยของคำจำกัดความที่มีอยู่ ขออภัย การดำเนินการนี้ไม่สามารถทำได้เนื่องจากคําจํากัดความของบล็อกไม่ใช่คลาส แต่เป็นมิกซ์อิน
เช่น คุณจะลบล้างพร็อพเพอร์ตี้สีไม่ได้เนื่องจากคำจำกัดความไม่มีพร็อพเพอร์ตี้สี แต่มีฟังก์ชัน init
ที่เรียก setColour
เพื่อตั้งค่าพร็อพเพอร์ตี้สีในบล็อกแทน เนื่องจากการเรียกใช้อยู่ภายใน init
จึงไม่มีวิธีแทนที่การเรียกใช้ดังกล่าวโดยไม่แทนที่ฟังก์ชัน init
ทั้งหมด
เขียนทับฟังก์ชันในคําจํากัดความที่มีอยู่
คุณสามารถเขียนทับฟังก์ชันในคําจํากัดความที่มีอยู่ได้ โดยทําดังนี้
Blockly.Blocks['existing_block'].init = function() {/*new function*/};
วิธีนี้ใช้ได้ แต่คุณต้องคัดลอกและแก้ไขฟังก์ชันที่มีอยู่ ไม่สามารถแทนที่เพียง 1 บรรทัดได้ การดำเนินการนี้มีปัญหาหลายประการ ดังนี้
- ซึ่งไม่ต่างกับการคัดลอกและแก้ไขคําจํากัดความทั้งฉบับ
- คุณใช้เพื่อแก้ไขฟังก์ชัน
init
ของบล็อกที่กําหนดไว้ใน JSON ไม่ได้ เช่น บล็อกในตัวของ Blockly เนื่องจากไม่มีinit
ฟังก์ชันที่จะคัดลอก ฟังก์ชันดังกล่าวสร้างขึ้นที่รันไทม์ - โดยคุณจะต้องกำหนดบล็อกโดยใช้ JavaScript ซึ่งอาจทำให้เกิดปัญหาเกี่ยวกับการแปล
เขียนทับผลลัพธ์ของ init
วิธี "แทนที่เพียง 1 บรรทัด" ของฟังก์ชัน init
คือแทนที่ฟังก์ชัน init
ด้วยฟังก์ชันที่เรียกใช้ฟังก์ชัน init
เดิม แล้วเขียนทับผลลัพธ์ของการเรียกใช้นั้น ตัวอย่างเช่น โค้ดต่อไปนี้จะเปลี่ยนสีของบล็อก logic_null
const originalInit = Blockly.Blocks['logic_null'].init;
Blockly.Blocks['logic_null'].init = function() {
originalInit.call(this);
this.setColour(300);
}
แต่น่าเสียดายที่วิธีนี้ไม่ค่อยมีประโยชน์เท่าที่ควร เช่น
การขยายการตรวจสอบการเชื่อมต่อหรือการใช้โปรแกรมตรวจสอบฟิลด์ที่เข้มงวดน้อยลงอาจทำให้สมมติฐานที่สร้างขึ้นโดยเครื่องมือสร้างโค้ดบล็อกและตัวแฮนเดิลเหตุการณ์เป็นโมฆะ
การแทนที่ช่องด้วยอินพุตค่าจะทําให้เครื่องมือสร้างโค้ดบล็อกและโปรแกรมตรวจสอบช่องใช้งานไม่ได้ และอาจทําให้ตัวแฮนเดิลเหตุการณ์ใช้งานไม่ได้ นอกจากนี้ ยังอาจทําได้ยากมากสําหรับบล็อกที่แปลแล้ว เนื่องจากภาษาที่ต่างกันอาจส่งผลให้บล็อกมีประเภทและลําดับของอินพุตและช่องที่แตกต่างกัน
เขียนทับคู่คีย์-ค่าในคําจํากัดความ JSON
หาก JSON ของบล็อกมีให้บริการแบบสาธารณะ คุณอาจเขียนทับค่า JSON แต่ละรายการได้ เช่น
// Block definition.
blockJson = {...};
Blockly.Blocks['my_block'] = {
init: function() {
initJson(blockJson); // Called when the block is created.
}
}
// Third-party code.
blockJson.colour = 100;
อย่างไรก็ตาม วิธีนี้จะใช้ได้ก็ต่อเมื่อออบเจ็กต์ JSON พร้อมใช้งานแบบสาธารณะ คําจํากัดความกําหนดฟังก์ชัน init
อย่างชัดแจ้ง และฟังก์ชัน init
เรียกใช้ initJson
การดำเนินการนี้จะไม่ทำงานหากมีการส่ง JSON ไปยัง defineBlocksWithJsonArray
หรือ createBlockDefinitionsFromJsonArray
เนื่องจากระบบจะประมวลผล JSON ก่อนที่บุคคลที่สามจะมีโอกาสแก้ไข (โปรดทราบว่าบล็อกในตัวของ Blockly ใช้ createBlockDefinitionsFromJsonArray
)
แต่จะเกิดอะไรขึ้นหากไม่ได้กำหนด JSON ด้วยวิธีนี้ ดูเหมือนว่าควรจะเขียนทับพร็อพเพอร์ตี้ JSON ได้อยู่ ไม่ได้ คำจำกัดความมีฟังก์ชัน init
(ไม่ใช่ JSON) และไม่มีฟังก์ชันที่จะแปลงฟังก์ชัน init
เป็น JSON
// Doesn't work. There is no getJson() function.
const json = Blockly.Blocks['existing_block'].getJson();
json['message0'] = 'my new message0';
Blockly.Blocks['existing_block'].init = function () {
initJson(json);
};
ออกแบบเพื่อใช้ซ้ำ
เมื่อออกแบบบล็อกที่กำหนดเอง คุณอาจออกแบบบล็อกในลักษณะที่ส่งเสริมการนำกลับมาใช้ซ้ำได้
ใช้ JSON ซ้ำ
หากมีบล็อก 2 รายการที่คล้ายกันมาก คุณสามารถสร้างคําจํากัดความ JSON หลักและนําไปใช้ซ้ำในคําจํากัดความย่อยได้ เช่น
const parentJson = {
// shared properties
};
Blockly.Blocks['child_block_1'] = {
init: function() {
initJson({...parentJson, colour: 100})
}
}
Blockly.Blocks['child_block_2'] = {
init: function() {
initJson({...parentJson, colour: 200})
}
}
อีกทางเลือกหนึ่งคือกําหนด JSON ของคุณในออบเจ็กต์ที่เผยแพร่ต่อสาธารณะ และส่งออบเจ็กต์นั้นไปยัง initJson
ในฟังก์ชัน init
ซึ่งทำให้ผู้อื่นเขียนทับพร็อพเพอร์ตี้แต่ละรายการได้ ดูข้อมูลเพิ่มเติมได้ที่เขียนทับคู่คีย์-ค่าในการคําจํากัดความ JSON
ใช้ฟังก์ชันซ้ำ
บล็อกอาจกำหนดฟังก์ชันมาตรฐานจำนวนหนึ่ง เช่น ตัวแฮนเดิลเหตุการณ์ระดับบล็อก เคล็ดลับเครื่องมือที่กำหนดเอง ตัวตรวจสอบฟิลด์ และฟังก์ชันที่ตัวเปลี่ยนรูปแบบใช้ รวมถึงฟังก์ชันที่ให้ลักษณะการทำงานที่กำหนดเอง เช่น ฟังก์ชันที่ตั้งค่าฟิลด์จากข้อมูลภายนอก เช่น ตำแหน่งปัจจุบันของแขนหุ่นยนต์
คุณอาจนำฟังก์ชันเหล่านี้ไปใช้ซ้ำในบล็อกต่างๆ ได้
ใช้ช่องเมนูแบบเลื่อนลง
หากมีชุดบล็อกที่เหมือนกันเกือบทั้งหมดยกเว้นโอเปอเรเตอร์ คุณอาจออกแบบบล็อกเดียวที่มีช่องแบบเลื่อนลงสำหรับโอเปอเรเตอร์ได้ เช่น
- บล็อก
logic_operation
ในตัวใช้เมนูแบบเลื่อนลงที่มีโอเปอเรเตอร์and
และor
- บล็อก
math_arithmetic
ในตัวใช้เมนูแบบเลื่อนลงที่มีโอเปอเรเตอร์+
,-
,×
,÷
และ^
โดยทั่วไปการเขียนเครื่องมือสร้างโค้ดสําหรับบล็อกดังกล่าวมีความซับซ้อนกว่าเล็กน้อย แต่ก็ยังคงง่ายกว่าการเขียนและดูแลรักษาบล็อกหลายรายการ
ใช้ตัวเปลี่ยน
หากมีชุดบล็อกที่แสดงโครงสร้างการเขียนโปรแกรมเดียวกันในลักษณะต่างๆ คุณอาจสร้างบล็อกเดียวที่ใช้ตัวเปลี่ยนรูปแบบได้ เช่น บล็อก controls_if
ในตัวสามารถแสดงคำสั่ง if-then-else
หลายรูปแบบ