Pertanyaan umum adalah cara mengubah definisi blok yang ada. Misalnya, Anda mungkin ingin menambahkan pemeriksaan koneksi atau mengubah kolom menjadi input nilai.
Secara umum, definisi blok tidak dapat diubah di tempat.
Cara mengubah definisi yang ada
Jika Anda ingin mengubah definisi jenis blok yang ada:
- Buat salinan definisi yang ada, termasuk generator kode blok.
- Ubah salinan dan beri nama baru untuk jenis Anda.
- Tambahkan definisi baru Anda ke
Blockly.Blocks
.
Mengapa saya tidak dapat langsung mengubah definisi yang ada?
Jika Anda ingin tahu mengapa Anda tidak dapat mengubah definisi yang ada, lanjutkan membaca. Kita akan mempertimbangkan beberapa kemungkinan.
Mengubah definisi yang ada secara langsung
Ada dua cara untuk mengubah definisi blok yang ada secara langsung: monkeypatching dan membuat fork kode. Keduanya sangat tidak dianjurkan, karena Anda akan berisiko merusak kode yang bergantung pada kode yang di-monkeypatch atau di-fork. Kedua teknik tersebut juga mempersulit integrasi update dan perbaikan bug. Untuk informasi selengkapnya, lihat Bagaimana dengan monkeypatching? dan Fork Blockly.
Membuat subclass definisi yang ada
Anda mungkin ingin membuat subclass definisi yang ada. Sayangnya,
hal ini tidak mungkin karena definisi blok bukan class, melainkan mixin.
Misalnya, tidak ada cara untuk menimpa properti warna karena
definisi tidak memiliki properti warna. Sebagai gantinya, fungsi ini memiliki fungsi init
yang memanggil setColour
untuk menetapkan properti warna pada blok. Karena panggilan
berada di dalam init
, tidak ada cara untuk menggantinya tanpa mengganti seluruh
fungsi init
.
Menimpa fungsi dalam definisi yang ada
Anda dapat menimpa fungsi dalam definisi yang ada:
Blockly.Blocks['existing_block'].init = function() {/*new function*/};
Cara ini berfungsi, tetapi Anda harus menyalin dan mengubah fungsi yang ada -- Anda tidak dapat mengganti hanya satu baris secara ajaib. Ada beberapa masalah terkait hal ini:
- Cara ini tidak jauh berbeda dengan menyalin dan mengubah seluruh definisi.
- Anda tidak dapat menggunakannya untuk mengubah fungsi
init
blok yang ditentukan dalam JSON, seperti blok bawaan Blockly. Hal ini karena tidak ada fungsiinit
yang akan disalin -- fungsi ini dibuat saat runtime. - Anda harus menentukan blok menggunakan JavaScript, yang dapat menyebabkan masalah dengan lokalisasi.
Menimpa hasil init
Salah satu cara untuk "mengganti hanya satu baris" fungsi init
adalah dengan mengganti
fungsi init
dengan fungsi yang memanggil fungsi init
asli, lalu
menulis ulang hasil panggilan tersebut. Misalnya, kode berikut mengubah
warna blok logic_null
:
const originalInit = Blockly.Blocks['logic_null'].init;
Blockly.Blocks['logic_null'].init = function() {
originalInit.call(this);
this.setColour(300);
}
Sayangnya, hal ini tidak terlalu berguna. Contoh:
Memperluas pemeriksaan koneksi atau menerapkan validator kolom yang kurang ketat dapat membatalkan asumsi yang dibuat oleh generator kode blok dan pengendali peristiwa.
Mengganti kolom dengan input nilai akan merusak generator kode blok dan validator kolom serta dapat merusak pengendali peristiwa. Hal ini mungkin juga sangat sulit dilakukan untuk blok yang dilokalkan karena lokalitas yang berbeda dapat menghasilkan blok dengan jenis dan urutan input dan kolom yang berbeda.
Menutupi pasangan nilai kunci dalam definisi JSON
Jika JSON untuk blok tersedia secara publik, Anda mungkin dapat menimpa setiap nilai JSON. Contoh:
// Block definition.
blockJson = {...};
Blockly.Blocks['my_block'] = {
init: function() {
initJson(blockJson); // Called when the block is created.
}
}
// Third-party code.
blockJson.colour = 100;
Namun, ini hanya berfungsi jika objek JSON tersedia secara publik, definisi menentukan fungsi init
secara eksplisit, dan fungsi init
memanggil
initJson
. Ini tidak berfungsi jika JSON diteruskan ke defineBlocksWithJsonArray
atau createBlockDefinitionsFromJsonArray
karena JSON diproses sebelum
pihak ketiga memiliki kesempatan untuk mengubahnya. (Perhatikan bahwa blok bawaan Blockly menggunakan
createBlockDefinitionsFromJsonArray
.)
Namun, bagaimana jika JSON tidak ditentukan dengan cara ini? Bukankah masih memungkinkan untuk
menulis ulang properti JSON? Sayangnya, tidak. Definisi ini berisi fungsi init
(bukan JSON) dan tidak ada fungsi untuk mengonversi fungsi init
menjadi 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);
};
Mendesain untuk digunakan kembali
Saat mendesain blok kustom Anda sendiri, Anda mungkin dapat mendesainnya dengan cara yang mendorong penggunaan kembali.
Menggunakan kembali JSON
Jika memiliki dua blok yang secara substansial serupa, Anda dapat membuat definisi JSON induk dan menggunakannya kembali dalam definisi turunan. Contoh:
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})
}
}
Alternatif lainnya adalah menentukan JSON dalam objek yang tersedia secara publik dan
meneruskan objek tersebut ke initJson
dalam fungsi init
Anda. Hal ini memungkinkan
orang lain menimpa setiap properti. Untuk mengetahui informasi selengkapnya, lihat
Menulis ulang pasangan nilai kunci dalam definisi
JSON.
Menggunakan kembali fungsi
Blok dapat menentukan sejumlah fungsi standar, seperti pengendali peristiwa tingkat blok, tooltip kustom, validator kolom, dan fungsi yang digunakan oleh pengubah, serta fungsi yang memberikan perilaku kustom, seperti fungsi yang menetapkan nilai kolom dari data eksternal, seperti posisi lengan robot saat ini.
Anda mungkin dapat menggunakan kembali fungsi ini di seluruh blok.
Menggunakan kolom dropdown
Jika memiliki kumpulan blok yang pada dasarnya sama, kecuali untuk operator, Anda mungkin dapat mendesain satu blok yang memiliki kolom dropdown untuk operator. Contoh:
- Blok
logic_operation
bawaan menggunakan dropdown dengan operatorand
danor
. - Blok
math_arithmetic
bawaan menggunakan dropdown dengan operator+
,-
,×
,÷
, dan^
.
Menulis generator kode untuk blok tersebut biasanya sedikit lebih kompleks, tetapi masih lebih mudah daripada menulis dan mengelola beberapa blok.
Menggunakan pengubah
Jika memiliki kumpulan blok yang mewakili variasi berbeda dari struktur
pemrograman yang sama, Anda mungkin dapat membuat satu blok yang menggunakan
mutator. Misalnya, blok controls_if
bawaan dapat mewakili beberapa variasi pernyataan
if-then-else
.