Tangani click tombol internal, lalu kirimkan CustomEvent bernama dari host komponen. Halaman yang menggunakan komponen mendengarkan pada host tersebut dan membaca event.detail. Panduan ini membuat demo browser lokal lengkap di Mac dan menjelaskan opsi peristiwa yang diperlukan setiap listener.
Tentukan notifikasi yang dibutuhkan konsumen Anda
Untuk komponen web JavaScript biasa, konsumen adalah halaman atau komponen pembungkus yang menggunakan elemen khusus Anda. Dalam contoh ini, tugas konkretnya adalah memungkinkan konsumen bereaksi saat seseorang mengaktifkan tombol internal, tanpa mencari DOM shadow komponen.
Contoh ini menggunakan ubin sintetis berlabel Tile A. Peristiwa publiknya adalah tile-activate, yang membawa itemId dan count aktivasi. CustomEvent menyediakan kolom detail untuk data aplikasi ini; nama peristiwanya peka huruf besar-kecil. Kode yang mengirimkan peristiwa dan listener harus menggunakan nama yang sama persis. Dokumentasi konstruktor CustomEvent.
Anggap pilihan tersebut sebagai kontrak antarmuka sederhana:
- Nama:
tile-activate. - Makna: tombol internal telah diaktifkan dan hitungannya diperbarui.
- Payload:
detail.itemIdmengidentifikasi ubin;detail.countberisi hitungan yang telah diperbarui. - Asal: host elemen khusus mengirimkan notifikasi.
- Pengiriman: konsumen langsung dan listener leluhur dapat menerimanya, termasuk melintasi batas shadow pembungkus.
Pilihan ini merupakan rancangan untuk contoh ini. Peristiwa yang berguna menjelaskan tindakan yang dipedulikan konsumen. Dengan begitu, komponen dapat mengubah markup internalnya nanti sambil mempertahankan antarmuka notifikasi yang sama.
Buat dan buka contoh lengkap di Mac Anda
Anda memerlukan browser desktop terkini dan editor teks biasa. Contoh satu file ini tidak memerlukan instalasi paket atau langkah build. Contoh ini menggunakan elemen khusus mandiri yang memperluas HTMLElement, pola platform yang didokumentasikan di bagian elemen khusus HTML Standard.
Di TextEdit, pilih File > New, lalu Format > Make Plain Text. Tempelkan dokumen lengkap di bawah ini. Pilih File > Save, beri nama component-click.html, lalu pilih Use .html jika diminta. Ini adalah langkah yang didokumentasikan Apple untuk membuat file HTML di TextEdit. Bekerja dengan dokumen HTML di TextEdit pada Mac.
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Component click notification</title>
</head>
<body>
<h1>Component click notification</h1>
<section id="demo">
<action-tile id="tile" item-id="tile-a"></action-tile>
<p id="direct-status">Direct listener: waiting</p>
<p id="parent-status">Parent listener: waiting</p>
</section>
<script>
class ActionTile extends HTMLElement {
constructor() {
super();
this._count = 0;
this._button = null;
this._root = this.attachShadow({ mode: "open" });
this._handleClick = () => {
this._count += 1;
this.dispatchEvent(new CustomEvent("tile-activate", {
detail: {
itemId: this.getAttribute("item-id"),
count: this._count
},
bubbles: true,
composed: true
}));
};
}
connectedCallback() {
if (!this._button) {
this._button = document.createElement("button");
this._button.type = "button";
this._button.textContent = "Activate Tile A";
this._root.append(this._button);
}
this._button.addEventListener("click", this._handleClick);
}
disconnectedCallback() {
this._button.removeEventListener("click", this._handleClick);
}
}
customElements.define("action-tile", ActionTile);
const tile = document.getElementById("tile");
const demo = document.getElementById("demo");
const directStatus = document.getElementById("direct-status");
const parentStatus = document.getElementById("parent-status");
tile.addEventListener("tile-activate", (event) => {
const { itemId, count } = event.detail;
directStatus.textContent =
`Direct listener: ${itemId}, activation ${count}`;
});
demo.addEventListener("tile-activate", (event) => {
const { itemId, count } = event.detail;
parentStatus.textContent =
`Parent listener: ${itemId}, activation ${count}`;
});
</script>
</body>
</html>
Buka file yang disimpan di browser Anda lalu klik Activate Tile A. Hasil pertama yang diharapkan adalah Direct listener: tile-a, activation 1 dan Parent listener: tile-a, activation 1. Setiap aktivasi berikutnya menambah kedua hitungan yang ditampilkan sebanyak satu. Ini adalah hasil yang diharapkan dari contoh, bukan hasil pengujian browser yang dilaporkan.
Urutan penting terlihat dalam kode: perbarui status komponen, buat notifikasi, kirimkan dari this, lalu biarkan konsumen memperbarui antarmukanya sendiri. dispatchEvent() memanggil listener yang berlaku secara sinkron sebelum kembali, sehingga konsumen melihat hitungan yang telah diperbarui saat handler mereka berjalan. Dokumentasi dispatchEvent.
Pilih opsi bubbling dan batas shadow yang tepat
Target pengiriman dan lokasi listener menentukan opsi mana yang penting. Listener yang dipasang langsung pada host menerima peristiwa yang dikirimkan pada host tersebut, meskipun bubbles bernilai false. Listener leluhur biasa memerlukan bubbling. Untuk melintasi batas shadow, diperlukan juga composed. Nilai default dasar untuk bubbles, composed, dan cancelable semuanya false. DOM Standard: antarmuka Event.
Tabel keputusan berikut disusun berdasarkan aturan propagasi tersebut. Tabel ini mengasumsikan listener biasa yang didaftarkan tanpa capture dan tidak ada handler yang menghentikan propagasi.
| Tempat peristiwa khusus dimulai | Tempat konsumen mendengarkan | Konfigurasi untuk rute tersebut |
|---|---|---|
| Host komponen | Host yang sama | Kedua flag tidak perlu bernilai true |
| Host komponen | Leluhur biasa di pohon yang sama | bubbles: true |
| Tombol shadow internal | Leluhur biasa di luar root shadow tersebut | bubbles: true, composed: true |
| Host komponen di dalam pohon shadow lain | Leluhur biasa di luar root shadow pembungkus | bubbles: true, composed: true |
Dalam demo ini, this.dispatchEvent(...) memulai notifikasi pada host. Karena itu, notifikasi tidak perlu keluar dari root shadow komponen itu sendiri. composed: true membuat notifikasi dapat digunakan melintasi batas shadow komponen pembungkus jika ubin ini nantinya ditempatkan di dalamnya. Jangkauan yang lebih luas tersebut harus menjadi bagian yang disengaja dari antarmuka publik. Dokumentasi properti composed pada Event.
Untuk percobaan terarah, ubah hanya bubbles: true menjadi bubbles: false, simpan, lalu muat ulang halaman. Saat diaktifkan, status langsung seharusnya diperbarui, sedangkan status induk tetap Parent listener: waiting. Setelah itu, pulihkan bubbling. Mengubah hanya composed menjadi false seharusnya membuat kedua listener tetap berfungsi dalam dokumen ini karena tidak satu pun rute melintasi batas shadow.
Pertahankan perilaku inisialisasi dan penyambungan ulang
Pengiriman peristiwa mungkin tampak benar pada awalnya, tetapi menghasilkan notifikasi ganda setelah komponen dipindahkan atau disambungkan kembali. Tegaskan tanggung jawab pembuatan, penyambungan, dan pembersihan.
Konstruktor memanggil super() terlebih dahulu, menginisialisasi status, lalu memasang root shadow. Rendering berlangsung di connectedCallback(), dengan pemeriksaan referensi tombol yang sudah ada agar hanya berjalan sekali. Pilihan ini mengikuti persyaratan konstruktor HTML Standard dan panduannya untuk melindungi inisialisasi yang tidak boleh diulang saat callback penyambungan dipanggil lagi. Persyaratan untuk konstruktor dan reaksi elemen khusus.
Komponen mendaftarkan listener klik internal saat tersambung dan menghapusnya saat terputus. Saat tersambung kembali, komponen menggunakan kembali tombol yang sudah ada dan mempertahankan _count. Callback penyambungan dan pemutusan adalah hook siklus hidup yang dipanggil saat elemen masuk dan keluar dari dokumen. Menggunakan elemen khusus.
Fungsi _handleClick yang disimpan itu penting: penghapusan harus mengidentifikasi fungsi yang sama dengan yang digunakan saat pendaftaran, dengan pengaturan capture yang sama. Membuat fungsi panah baru dalam pemanggilan penghapusan tidak akan mengidentifikasi listener yang telah didaftarkan. Dokumentasi removeEventListener.
Jika Anda menambahkan listener ke window, document, atau target eksternal lain dalam komponen yang lebih besar, pastikan pembersihannya juga sama jelasnya. Pisahkan perubahan siklus hidup dari makna notifikasi agar penyambungan ulang elemen tidak tanpa sengaja mengumumkan tindakan pengguna.
Diagnosis notifikasi yang hilang atau berulang
Gunakan dua baris status yang terlihat untuk menemukan sumber kegagalan sebelum mengubah flag peristiwa. Keduanya membedakan masalah notifikasi komponen dari masalah pengiriman ke leluhur.
- Kedua status tidak berubah: bandingkan nama peristiwa saat pengiriman dan pendaftaran, lalu periksa apakah definisi elemen khusus dan handler tombol dijalankan. Dalam dokumen ini, listener konsumen didaftarkan sebelum pengguna melakukan aktivasi.
- Hanya status langsung yang berubah: periksa
bubbles. Periksa juga handler perantara yang menghentikan propagasi. - Pengiriman gagal hanya saat elemen berada di dalam komponen lain: identifikasi batas shadow pada rute tersebut dan periksa
composed. - Hitungan melonjak setelah penyambungan ulang: periksa pendaftaran listener yang berulang, terutama fungsi anonim baru yang dibuat setiap kali elemen tersambung.
Fungsi anonim yang berulang merupakan objek listener terpisah, meskipun teks sumbernya identik. Referensi fungsi yang stabil memudahkan penalaran tentang pendaftaran dan pembersihan. addEventListener() juga membedakan opsi capture listener, yang memengaruhi kapan listener berjalan. Dokumentasi addEventListener.
click native mungkin sudah mencapai luar pohon shadow karena klik yang dikirimkan browser bersifat composed. Peristiwa khusus terpisah berguna ketika konsumen memerlukan tindakan komponen bernama dan payload yang ditentukan. Hindari menangani kedua notifikasi sebagai tindakan aplikasi yang sama, kecuali penggandaan itu memang disengaja. Dokumentasi properti composed pada Event.
Terakhir, bedakan notifikasi dari izin untuk melanjutkan dalam rancangan peristiwa Anda. Contoh ini menambah hitungan sebelum pengiriman dan membiarkan peristiwanya noncancelable. Konsumen yang memanggil preventDefault() tidak dapat membatalkan pembaruan itu. Permintaan yang cancelable memerlukan implementasi eksplisit yang memeriksa nilai kembalian dispatchEvent() sebelum melakukan tindakan yang diminta. Nilai kembalian dispatchEvent.
Untuk tugas ini, kontrak lengkapnya sederhana: satu handler tombol internal memperbarui status, satu peristiwa khusus bernama dikirimkan dari host, dan konsumen membaca payload yang didokumentasikan. Pastikan listener langsung berfungsi terlebih dahulu, lalu aktifkan rute propagasi yang benar-benar dibutuhkan antarmuka pembungkus Anda.
Sumber
- HTML Standard — Elemen khusus — WHATWG.
- DOM Standard — WHATWG.
- CustomEvent: konstruktor CustomEvent() — MDN Web Docs.
- EventTarget: metode dispatchEvent() — MDN Web Docs.
- Event: properti composed — MDN Web Docs.
- Menggunakan elemen khusus — MDN Web Docs.
- EventTarget: metode addEventListener() — MDN Web Docs.
- EventTarget: metode removeEventListener() — MDN Web Docs.
- Bekerja dengan dokumen HTML di TextEdit pada Mac — Apple.