Elemen kustom memungkinkan Anda membuat tag HTML sendiri. Checklist ini mencakup praktik terbaik untuk membantu Anda membuat elemen berkualitas tinggi.
Elemen khusus memungkinkan Anda memperluas HTML dan menentukan tag Anda sendiri. Mereka adalah
fitur yang sangat kuat, tetapi mereka juga
tingkat rendah, yang berarti itu tidak
selalu mengetahui cara terbaik untuk
mengimplementasikan elemen Anda sendiri.
Untuk membantu Anda menciptakan pengalaman terbaik, kami telah menyusun
{i>checklist<i} ini. Ini menguraikan semua hal yang
kita pikir diperlukan untuk menjadi
elemen kustom yang berperilaku baik.
Checklist
DOM Bayangan
Membuat root bayangan untuk mengenkapsulasi gaya. |
Mengapa demikian? |
Mengenkapsulasi gaya dalam shadow root elemen Anda memastikan bahwa elemen ini akan berfungsi
terlepas dari tempat penggunaannya. Hal ini sangat penting
jika seorang developer
ingin menempatkan elemen Anda di dalam
{i>shadow root<i} elemen yang lain. Ini
berlaku bahkan untuk elemen sederhana
seperti kotak centang atau tombol pilihan. Mungkin
jika satu-satunya konten di dalam
{i>shadow root<i} Anda adalah gaya
itu sendiri.
|
Contoh |
Elemen <howto-checkbox> .
|
Buat shadow root di konstruktor.
|
Mengapa demikian? |
Konstruktor adalah saat Anda memiliki pengetahuan eksklusif tentang elemen.
Inilah saat yang tepat untuk menyiapkan detail implementasi yang tidak Anda inginkan
elemen yang berantakan. Melakukan pekerjaan ini di callback berikutnya, seperti
connectedCallback , berarti Anda harus mencegah
situasi ketika elemen Anda dilepas kemudian
dipasang kembali ke dokumen.
|
Contoh |
Elemen <howto-checkbox> .
|
Tempatkan setiap turunan yang dibuat elemen ke dalam shadow root-nya.
|
Mengapa demikian? |
Turunan yang dibuat oleh elemen Anda adalah bagian dari implementasinya dan harus
pribadi. Tanpa perlindungan {i>shadow root<i}, JavaScript luar dapat
secara tidak sengaja mengganggu anak-anak ini.
|
Contoh |
Elemen <howto-tabs> .
|
Gunakan <slot> untuk memproyeksikan turunan light DOM ke dalam shadow DOM Anda
|
Mengapa demikian? |
Izinkan pengguna komponen Anda untuk menentukan konten dalam komponen karena turunan HTML membuat komponen Anda lebih dapat disusun. Jika browser tidak mendukung elemen kustom, konten bertingkat akan tetap tersedia, terlihat, dan dapat diakses.
|
Contoh |
Elemen <howto-tabs> .
|
Tetapkan gaya tampilan :host (misalnya, block ,
inline-block , flex ) kecuali jika Anda lebih memilih default
inline .
|
Mengapa demikian? |
Elemen kustom bernilai display: inline secara default. Jadi, menyetel elemen kustom
width atau height tidak akan berpengaruh. Hal ini sering
mengejutkan developer dan dapat menyebabkan masalah yang terkait dengan
mengatur tata letak halaman. Kecuali Anda lebih memilih tampilan inline , Anda
harus selalu menetapkan nilai display default.
|
Contoh |
Elemen <howto-checkbox> .
|
Tambahkan gaya tampilan :host yang mengikuti atribut tersembunyi.
|
Mengapa demikian? |
Elemen kustom dengan gaya display default, misalnya,
:host { display: block } , akan mengganti kekhususan yang lebih rendah
bawaan
Atribut hidden .
Anda mungkin terkejut jika ingin menyetel hidden
pada elemen Anda untuk merendernya menjadi display: none . Selain itu
ke gaya display default, tambahkan dukungan untuk hidden
dengan :host([hidden]) { display: none } .
|
Contoh |
Elemen <howto-checkbox> .
|
Atribut dan properti
Jangan ganti atribut global set penulis.
|
Mengapa demikian? |
Atribut global adalah atribut yang ada pada semua elemen HTML. Agak besar
contoh mencakup tabindex dan role . Elemen kustom
mungkin ingin menyetel tabindex awalnya ke 0 sehingga akan menjadi keyboard
dapat difokuskan. Tetapi Anda harus selalu memeriksa terlebih dahulu
untuk melihat apakah pengembang menggunakan
elemen Anda telah menetapkannya ke nilai lain. Misalnya, jika mereka telah menetapkan
tabindex ke -1, itu merupakan sinyal bahwa mereka tidak menginginkan
menjadi interaktif.
|
Contoh |
Elemen <howto-checkbox> . Hal ini dijelaskan lebih lanjut dalam
Jangan ganti penulis halaman.
|
Selalu terima data primitif (string, angka, boolean) sebagai atribut
atau properti.
|
Mengapa demikian? |
Elemen khusus, seperti komponen bawaannya, harus dapat dikonfigurasi.
Konfigurasi dapat diteruskan secara deklaratif, melalui atribut, atau secara imperatif
melalui properti JavaScript. Idealnya, setiap atribut juga harus ditautkan ke
properti yang sesuai.
|
Contoh |
Elemen <howto-checkbox> .
|
Upayakan untuk menjaga atribut dan properti data primitif tetap sinkron, yang tercermin dari
dari atribut ke atribut, dan sebaliknya.
|
Mengapa demikian? |
Anda tidak pernah tahu bagaimana pengguna akan berinteraksi dengan elemen Anda. Mereka mungkin
menetapkan properti di JavaScript, lalu memperkirakan akan membaca nilai tersebut
menggunakan API seperti getAttribute() . Jika setiap atribut memiliki
properti yang sesuai, dan keduanya mencerminkan, hal itu akan memudahkan
pengguna untuk bekerja
dengan elemen Anda. Dengan kata lain, memanggil
setAttribute('foo', value) juga harus menetapkan atribut
properti foo dan sebaliknya. Tentu saja ada pengecualian untuk
aturan ini. Anda tidak boleh mencerminkan properti frekuensi tinggi, mis.
currentTime di pemutar video. Gunakan penilaian terbaik Anda. Jika ya
terlihat seperti pengguna akan berinteraksi dengan
properti atau atribut, dan
tidak membebani untuk mencerminkannya, maka lakukanlah itu.
|
Contoh |
Elemen <howto-checkbox> . Hal ini dijelaskan lebih lanjut dalam
Hindari masalah reentransi.
|
Usahakan untuk hanya menerima data lengkap (objek, array) sebagai properti.
|
Mengapa demikian? |
Secara umum, tidak ada contoh elemen HTML {i>built-in<i} yang
menerima data lengkap (objek dan array JavaScript polos) melalui
. Data lengkap diterima baik melalui panggilan metode atau
properti baru. Ada beberapa kelemahan yang jelas
dari menerima data lengkap sebagai
atribut tambahan: mahal untuk membuat serialisasi objek besar ke string, dan
dalam proses stringifikasi ini, referensi objek apa pun akan hilang. Sebagai
misalnya, jika Anda membuat string objek yang memiliki referensi ke objek lain,
atau mungkin simpul DOM, referensi itu akan hilang.
|
Jangan mencerminkan properti data lengkap ke atribut.
|
Mengapa demikian? |
Merefleksikan properti data lengkap ke atribut
memang sangat mahal,
yang memerlukan serialisasi dan deserialisasi objek JavaScript yang sama. Kecuali
Anda memiliki kasus penggunaan yang hanya
dapat diselesaikan dengan fitur ini,
sebaiknya hindari itu.
|
Pertimbangkan untuk memeriksa properti yang mungkin telah ditetapkan sebelum elemen
diupgrade.
|
Mengapa demikian? |
Developer yang menggunakan elemen Anda dapat mencoba menetapkan properti pada elemen tersebut
sebelum definisinya dimuat. Terutama jika
developer menggunakan framework yang menangani pemuatan komponen, menyegelnya
ke halaman, dan mengikat propertinya ke model.
|
Contoh |
Elemen <howto-checkbox> . Dijelaskan lebih lanjut di
Buat properti menjadi lambat.
|
Jangan menerapkan kelas secara mandiri.
|
Mengapa demikian? |
Elemen yang perlu mengekspresikan statusnya harus menggunakan atribut. Tujuan
Atribut class umumnya dianggap dimiliki oleh
yang menggunakan elemen Anda, dan menulisnya sendiri mungkin secara tidak sengaja
menginjak kelas developer.
|
Acara
Mengirim peristiwa sebagai respons terhadap aktivitas komponen internal.
|
Mengapa demikian? |
Komponen Anda mungkin memiliki properti yang berubah sebagai respons terhadap aktivitas yang
hanya komponen Anda yang tahu, misalnya, jika timer atau animasi
selesai, atau resource selesai dimuat. Sangat membantu untuk mengirim peristiwa
sebagai respons terhadap perubahan ini untuk
memberi tahu {i>host<i} bahwa status komponen
berbeda.
|
Jangan mengirim peristiwa sebagai respons terhadap setelan properti host (yang
aliran data).
|
Mengapa demikian? |
Mengirim peristiwa untuk merespons setelan host properti berlebihan
({i>host<i} mengetahui keadaan saat ini karena ia baru saja mengaturnya). Mengirim peristiwa
sebagai respons terhadap setelan host, properti dapat menyebabkan loop data yang tidak terbatas
sistem binding.
|
Contoh |
Elemen <howto-checkbox> .
|
Penjelasan
Jangan ganti penulis halaman
Mungkin saja pengembang yang menggunakan elemen Anda ingin mengganti beberapa
ke keadaan awal. Misalnya, mengubah role
ARIA atau kemampuan fokusnya dengan
tabindex
. Periksa untuk melihat apakah atribut ini dan
atribut global lainnya telah ditetapkan,
sebelum menerapkan nilai Anda sendiri.
connectedCallback() {
if (!this.hasAttribute('role'))
this.setAttribute('role', 'checkbox');
if (!this.hasAttribute('tabindex'))
this.setAttribute('tabindex', 0);
Membuat properti menjadi lambat
Pengembang mungkin mencoba untuk menetapkan properti pada elemen Anda sebelum
telah dimuat. Terutama jika pengembang menggunakan
yang menangani pemuatan komponen, memasukkannya ke dalam halaman, dan
mengikat propertinya ke model.
Pada contoh berikut, Angular secara deklaratif mengikat elemen
isChecked
ke properti checked
kotak centang. Jika definisi untuk
kotak centang petunjuk dimuat dengan lambat, mungkin saja Angular mungkin mencoba menetapkan
properti yang dicentang sebelum elemen diupgrade.
<howto-checkbox [checked]="defaults.isChecked"></howto-checkbox>
Elemen khusus harus menangani skenario ini dengan memeriksa apakah ada properti
yang sudah ditetapkan pada instance-nya. <howto-checkbox>
menunjukkan pola ini menggunakan metode yang disebut _upgradeProperty()
.
connectedCallback() {
...
this._upgradeProperty('checked');
}
_upgradeProperty(prop) {
if (this.hasOwnProperty(prop)) {
let value = this[prop];
delete this[prop];
this[prop] = value;
}
}
_upgradeProperty()
mengambil nilai dari instance yang belum diupgrade dan menghapusnya
properti agar tidak membayangi penyetel properti elemen kustom itu sendiri.
Dengan cara ini, ketika definisi elemen akhirnya dimuat, ia bisa segera
menunjukkan keadaan yang benar.
Menghindari masalah reentransi
Anda mungkin ingin menggunakan attributeChangedCallback()
untuk mencerminkan status ke
properti pokok, misalnya:
// When the [checked] attribute changes, set the checked property to match.
attributeChangedCallback(name, oldValue, newValue) {
if (name === 'checked')
this.checked = newValue;
}
Namun, hal ini bisa menimbulkan loop tak terbatas
jika penyetel properti juga mencerminkan
atribut ini.
set checked(value) {
const isChecked = Boolean(value);
if (isChecked)
// OOPS! This will cause an infinite loop because it triggers the
// attributeChangedCallback() which then sets this property again.
this.setAttribute('checked', '');
else
this.removeAttribute('checked');
}
Alternatifnya adalah dengan memungkinkan penyetel properti untuk tercermin ke atribut, dan
meminta pengambil menentukan nilainya berdasarkan atribut.
set checked(value) {
const isChecked = Boolean(value);
if (isChecked)
this.setAttribute('checked', '');
else
this.removeAttribute('checked');
}
get checked() {
return this.hasAttribute('checked');
}
Dalam contoh ini, menambahkan atau menghapus atribut juga akan menetapkan properti.
Terakhir, attributeChangedCallback()
dapat digunakan untuk menangani efek samping
seperti menerapkan status ARIA.
attributeChangedCallback(name, oldValue, newValue) {
const hasValue = newValue !== null;
switch (name) {
case 'checked':
// Note the attributeChangedCallback is only handling the *side effects*
// of setting the attribute.
this.setAttribute('aria-checked', hasValue);
break;
...
}
}