Pengenalan Web Components

Konsep custom element dan kedudukan shadow DOM.

Daftar isi

HTML menyediakan elemen bawaan untuk hampir semua kebutuhan konten, tetapi antarmuka yang digunakan berulang di banyak halaman membutuhkan perangkat lain. Web components adalah sekumpulan teknologi standar untuk mendefinisikan custom element, yaitu tag baru yang diperlakukan browser sebagaimana tag bawaan. Topik ini membahas tiga teknologinya secara ringkas, kedudukan shadow DOM dalam kelompok itu, dan alasan pembahasan pada jalur HTML cukup sampai pengenalannya.

Tiga teknologi dalam satu payung#

Istilah web components bukan satu API tunggal, melainkan payung bagi tiga teknologi yang saling melengkapi. Custom element mendefinisikan tag baru beserta perilakunya, sedangkan shadow DOM mengisolasi struktur dan gaya komponen dari halaman di luarnya. Pasangan elemen template dan slot menyimpan cetakan markup dan menampung isi yang berasal dari luar komponen. Ketiganya ditetapkan pada spesifikasi HTML Living Standard dan DOM, sehingga tidak memerlukan library eksternal.

TeknologiTugas utamaPerangkat kuncinya
custom elementmendefinisikan tag baru beserta perilakunyacustomElements.define()
shadow DOMmengisolasi struktur dan gaya komponenattachShadow()
template dan slotmenyimpan cetakan markup dan menampung isielemen template dan slot

Ketiga teknologi digunakan bersama pada praktiknya, tetapi masing-masing juga dapat berdiri sendiri. Halaman dapat menggunakan template tanpa elemen kustom sama sekali, dan elemen kustom sederhana dapat bekerja tanpa shadow DOM. Pembagian tugas ini membuat pembelajarannya bertahap, bukan sekali jadi.

Mendefinisikan elemen kustom#

Elemen kustom didaftarkan melalui metode customElements.define() dengan dua masukan, yaitu nama tagnya dan class yang menjelaskan perilakunya. Nama tag wajib memuat tanda hubung, misalnya kartu-catatan, dan aturan ini mencegah bentrokan dengan tag bawaan maupun tag yang mungkin ditambahkan di masa depan. Pendaftaran yang gagal, misalnya karena nama tanpa tanda hubung, melempar error dan tag tersebut tidak pernah diperlakukan sebagai komponen.

Class pendefinisinya mewarisi HTMLElement dan dapat merespons siklus hidup (lifecycle) yang singkat. Constructor menyiapkan keadaan awal, connectedCallback berjalan ketika elemen masuk ke dokumen, dan attributeChangedCallback berjalan ketika atribut yang diawasi berubah. Dua callback terakhir itu sudah menutup kebutuhan banyak komponen sederhana.

js Pendaftaran elemen kustom kartu-catatan
// tidak-dijalankan
class KartuCatatan extends HTMLElement {
  constructor() {
    super(); // wajib menjadi baris pertama dalam constructor
  }
  connectedCallback() {
    console.log("kartu-catatan masuk ke dokumen");
  }
}

customElements.define("kartu-catatan", KartuCatatan);

Skrip di atas menggunakan API browser sehingga tidak dieksekusi di lingkungan Node, tetapi strukturnya menunjukkan pola baku pendaftaran. Elemen kartu-catatan yang sudah ada di markup diperbarui (upgrade) menjadi komponen seketika begitu pendaftarannya dijalankan, dan elemen baru yang ditambahkan kemudian langsung mengikuti perilaku yang sama. Pendaftaran hanya perlu ditulis sekali untuk seluruh halaman.

Kedudukan shadow DOM#

Shadow DOM adalah pohon DOM tersembunyi yang dipasangkan pada sebuah elemen, dan isinya tidak bercampur dengan pohon dokumen utama. Isolasi itu berlaku dua arah, yaitu CSS halaman tidak menyusup ke dalam komponen, sedangkan CSS komponen tidak menjalar keluar ke halaman. Browser sendiri sudah menggunakan teknik ini pada kontrol bawaannya, misalnya tombol putar pada elemen video yang struktur internalnya tidak terlihat dari luar.

Pemasangannya dilakukan melalui metode attachShadow() yang mengembalikan shadow root, yaitu akar pohon bayangan itu. Gaya dan cetakan komponen ditempelkan di dalamnya, sedangkan konten yang ditulis pengguna tetap berada di luar dan masuk melalui elemen slot. Dengan pembagian ini, satu komponen tetap konsisten di halaman mana pun komponen itu ditempatkan, tanpa bergantung pada CSS halamannya.

Pada tumpukan teknologi web, shadow DOM menempati posisi perantara antara markup dan skrip. Definisi shadow DOM ada pada spesifikasi DOM dan HTML, tetapi pemasangannya hanya dapat dilakukan lewat JavaScript, sehingga pembahasan HTML memang berhenti pada tahap pengenalan. Pola pikir yang tepat adalah memperlakukan elemen kustom seperti elemen bawaan, yaitu bagian markup yang perilakunya sudah ditangani oleh komponennya.

Kapan web components tepat digunakan#

Web components paling menguntungkan untuk antarmuka yang digunakan berulang di banyak halaman, terutama ketika halaman-halaman itu tidak menumpang satu framework yang sama. Elemen kustom tidak terikat framework, sehingga komponen yang ditulis sekali dapat dipasang pada proyek yang berbeda tanpa penyesuaian besar. Keuntungan inilah yang menjadikannya pilihan umum untuk sistem desain sebuah organisasi.

Sebaliknya, kebutuhan yang sudah dijawab elemen bawaan tidak perlu dijadikan komponen. Elemen select, button, dan details menyertakan aksesibilitas serta perilaku yang sudah teruji bertahun-tahun, sedangkan komponen buatan sendiri harus mengejar keduanya dari nol. Aturan praktisnya sederhana, yaitu gunakan elemen bawaan terlebih dahulu dan pindah ke elemen kustom hanya bila tidak ada yang memadai.

Sebagai pengenalan pada jalur HTML, pembahasan web components memang cukup sampai sini. Implementasi penuh, termasuk pengelolaan atribut, event, dan gaya yang kompleks, menuntut kemampuan JavaScript, sehingga pengerjaannya menjadi milik jalur JavaScript. Yang diharapkan dari tingkat HTML adalah membaca tag kustom dengan tenang dan mengetahui apa yang terjadi di baliknya.

Berkas utuh web components sederhana#

Berkas berikut mengumpulkan ketiga teknologi pada satu halaman yang dapat dibuka langsung di browser. Elemen kartu-catatan didefinisikan lewat customElements.define(), struktur dan gayanya dipasang pada shadow root, sedangkan judul dan isi tiap kartu disuntikkan melalui slot dari markup di luarnya. Kedua kartu tampak berbeda isinya, tetapi keduanya menggunakan satu definisi yang sama.

html komponen.html
<!DOCTYPE html>
<html lang="id">
<head>
  <meta charset="utf-8">
  <title>Kartu catatan sebagai web component</title>
  <style>
    body { font-family: sans-serif; max-width: 30rem; margin: 0 auto; padding: 0 1rem; color: #222222; }
  </style>
</head>
<body>
  <h1>Catatan harian</h1>

  <template id="polakartu">
    <style>
      .kartu { border: 1px solid #999999; border-radius: 6px; padding: 0.5rem 0.75rem; margin: 0.5rem 0; }
      .judul { font-weight: 700; color: #223344; }
    </style>
    <div class="kartu">
      <p class="judul"><slot name="judul">Tanpa judul</slot></p>
      <p><slot>Isi kartu kosong.</slot></p>
    </div>
  </template>

  <kartu-catatan>
    <span slot="judul">Belanja mingguan</span>
    Beras 5 kg, minyak 1 L, telur satu pek.
  </kartu-catatan>

  <kartu-catatan>
    <span slot="judul">Jadwal siaran</span>
    Daftar putar diperbarui setiap hari Sabtu.
  </kartu-catatan>

  <script>
    class KartuCatatan extends HTMLElement {
      connectedCallback() {
        if (this.shadowRoot) return; // mencegah pemasangan ganda
        const pola = document.getElementById("polakartu");
        const bayangan = this.attachShadow({ mode: "open" });
        bayangan.appendChild(pola.content.cloneNode(true));
      }
    }
    customElements.define("kartu-catatan", KartuCatatan);
  </script>
</body>
</html>

Pada berkas itu, elemen template menyimpan kartu tanpa pernah dirender sampai salinannya dipasang ke shadow root. Slot bernama judul menampung span beratribut slot, sedangkan slot tanpa nama menampung sisa isi kartu. Pemeriksaan this.shadowRoot di awal connectedCallback mencegah pemasangan ganda ketika elemen dipindahkan dalam dokumen.

Kesalahan umum#

  • Menulis nama elemen kustom tanpa tanda hubung. Pendaftarannya melempar error, dan tag tersebut diperlakukan browser sebagai elemen tak dikenal yang tanpa perilaku.
  • Lupa memanggil super() di baris pertama constructor. Error dihasilkan seketika dan elemen tidak pernah terdaftar sebagai komponen.
  • Mengharapkan CSS halaman menata isi di dalam shadow root. Isolasi gaya bekerja dua arah, sehingga gaya komponen harus ditulis di dalamnya atau diteruskan melalui custom property, yaitu variabel CSS.

Ringkasan#

  • Web components menggabungkan custom element, shadow DOM, serta template dan slot untuk mendefinisikan elemen kustom standar.
  • Pendaftaran berlangsung melalui customElements.define() dengan nama tag yang wajib memuat tanda hubung.
  • Shadow DOM mengisolasi struktur dan gaya komponen dari halaman, sehingga satu komponen konsisten di halaman mana pun komponen itu dipasang.
  • Elemen bawaan tetap diutamakan, dan implementasi penuh komponen menuntut JavaScript yang dibahas pada jalurnya sendiri.

Referensi#