[Nasihat membaca] 19 bagian siklus lainnya Hari ini, dalam terjemahan 17 bagian materi yang dikhususkan untuk fitur segala sesuatu yang terhubung dengan JavaScript, kita akan berbicara tentang komponen web dan berbagai standar yang ditujukan untuk bekerja dengannya. Perhatian khusus akan diberikan pada teknologi Shadow DOM.

Ulasan
Komponen web adalah keluarga API yang dirancang untuk menjelaskan elemen DOM baru yang cocok untuk digunakan kembali. Fungsionalitas elemen-elemen tersebut dipisahkan dari sisa kode, mereka dapat digunakan dalam aplikasi web dari desain kita sendiri.
Ada empat teknologi yang terkait dengan komponen web:
- Shadow DOM (Shadow DOM)
- Template HTML (Template HTML)
- Elemen Khusus
- Impor HTML (Impor HTML)
Pada artikel ini, kita akan berbicara tentang teknologi Shadow DOM, yang dirancang untuk membuat aplikasi berbasis komponen. Ini menawarkan cara untuk memecahkan masalah pengembangan web umum yang mungkin pernah Anda temui:
- DOM isolasi: komponen memiliki pohon DOM yang terisolasi (ini berarti bahwa perintah
document.querySelector()
tidak akan mengizinkan akses ke node dalam bayangan DOM komponen). Selain itu, ini menyederhanakan sistem pemilih CSS dalam aplikasi web, karena komponen DOM terisolasi, yang memungkinkan pengembang untuk menggunakan pengidentifikasi universal dan nama kelas yang sama dalam komponen yang berbeda tanpa khawatir tentang kemungkinan konflik nama. - Isolasi CSS: Aturan CSS yang dijelaskan di dalam shadow DOM terbatas padanya. Gaya-gaya ini tidak meninggalkan elemen, mereka tidak bercampur dengan gaya halaman lainnya.
- Komposisi: Mengembangkan API deklaratif untuk komponen berbasis markup.
Teknologi Shadow DOM
Diasumsikan bahwa Anda sudah terbiasa dengan konsep DOM dan API terkait. Jika tidak, Anda dapat membaca materi
ini .
Shadow DOM pada dasarnya sama dengan DOM biasa, tetapi dengan dua perbedaan:
- Yang pertama adalah bagaimana Shadow DOM dibuat dan digunakan, khususnya, ini tentang hubungan Shadow DOM dengan sisa halaman.
- Yang kedua adalah perilaku Shadow DOM dalam kaitannya dengan halaman.
Saat bekerja dengan DOM, node DOM dibuat yang bergabung, sebagai anak-anak, ke elemen halaman lainnya. Dalam kasus teknologi Shadow DOM, pohon DOM terisolasi dibuat yang bergabung dengan elemen, tetapi dipisahkan dari elemen anak normal.
Subtree yang terisolasi ini disebut pohon bayangan. Elemen yang melekat pada pohon tersebut disebut sebagai host bayangan. Segala sesuatu yang ditambahkan ke subtree bayangan DOM ternyata lokal ke elemen yang dilampirkan, termasuk gaya yang dijelaskan menggunakan
<style>
. Ini adalah bagaimana isolasi CSS disediakan melalui teknologi Shadow DOM.
Membuat Shadow DOM
Root shadow adalah bagian dari dokumen yang menempel pada elemen host. Suatu elemen memperoleh DOM bayangan ketika elemen root shadow terpasang padanya. Untuk membuat bayangan DOM untuk elemen tertentu, Anda perlu menggunakan perintah dari form
element.attachShadow()
:
var header = document.createElement('header'); var shadowRoot = header.attachShadow({mode: 'open'}); shadowRoot.appendChild(document.createElement('<p> Shadow DOM </p>');
Perlu dicatat bahwa dalam
spesifikasi Shadow DOM terdapat daftar elemen yang tidak dapat dihubungkan oleh sub-layer shadow DOM.
Komposisi dalam Shadow DOM
Komposisi adalah salah satu fitur terpenting dari Shadow DOM, itu adalah cara untuk membuat aplikasi web, yang digunakan dalam proses penulisan kode HTML. Selama proses ini, programmer menggabungkan berbagai blok penyusun (elemen) yang membentuk halaman, bersarang, jika perlu, satu sama lain. Misalnya, ini adalah elemen seperti
<div>
,
<header>
,
<form>
, dan lainnya yang digunakan untuk membuat antarmuka aplikasi web, termasuk yang bertindak sebagai wadah untuk elemen lain.
Komposisi menentukan kemampuan elemen, seperti
<select>
,
<form>
,
<video>
, untuk memasukkan elemen HTML lain sebagai anak-anak, dan kemampuan untuk mengatur perilaku khusus dari struktur tersebut yang terdiri dari elemen yang berbeda.
Misalnya, elemen
<select>
memiliki sarana untuk merender elemen
<option>
dalam bentuk daftar drop-down dengan konten yang telah ditentukan sebelumnya dari elemen-elemen dari daftar tersebut.
Pertimbangkan beberapa fitur Shadow DOM yang digunakan dalam menyusun elemen.
Dom cahaya
Light DOM adalah markup yang dibuat oleh pengguna komponen Anda. DOM ini berada di luar bayangan DOM komponen dan merupakan anak dari komponen. Bayangkan Anda membuat komponen khusus yang disebut
<better-button>
yang memperluas kemampuan elemen
<button>
HTML standar, dan pengguna perlu menambahkan gambar dan beberapa teks ke elemen baru ini. Begini tampilannya:
<extended-button> <img align="center" src="boot.png" slot="image"> <span>Launch</span> </extended-button>
Elemen
<extended-button>
adalah komponen khusus yang dijelaskan sendiri oleh programmer, dan kode HTML di dalam komponen ini adalah Light DOM - yang ditambahkan oleh pengguna komponen ini.
Bayangan DOM dalam contoh ini adalah komponen
<extended-button>
. Ini adalah model objek lokal dari komponen yang menggambarkan struktur internalnya, terisolasi dari dunia luar CSS, dan merangkum detail implementasi komponen.
Dom rata
Pohon DOM rata mewakili bagaimana browser menampilkan komponen pada layar, menggabungkan Light DOM dan Shadow DOM. Ini adalah pohon DOM yang dapat dilihat di alat pengembang, dan itu yang ditampilkan pada halaman. Mungkin terlihat seperti ini:
<extended-button> #shadow-root <style>…</style> <slot name="image"> <img align="center" src="boot.png" slot="image"> </slot> <span id="container"> <slot> <span>Launch</span> </slot> </span> </extended-button>
Pola
Jika Anda harus terus-menerus menggunakan struktur yang sama dalam markup HTML halaman web, akan berguna untuk menggunakan template tertentu alih-alih menulis kode yang sama berulang kali. Ini mungkin sebelumnya, tetapi sekarang semuanya telah sangat disederhanakan berkat penampilan
<template>
HTML, yang menikmati dukungan luar biasa untuk peramban modern. Elemen ini dan isinya tidak ditampilkan di DOM, tetapi Anda dapat menggunakannya dari JavaScript. Pertimbangkan contoh sederhana:
<template id="my-paragraph"> <p> Paragraph content. </p> </template>
Jika Anda memasukkan desain ini dalam markup HTML halaman, konten tag
<p>
dijelaskan olehnya tidak akan muncul di layar hingga secara eksplisit dilampirkan ke DOM dokumen. Misalnya, mungkin terlihat seperti ini:
var template = document.getElementById('my-paragraph'); var templateContent = template.content; document.body.appendChild(templateContent);
Ada cara lain untuk mencapai efek yang sama, tetapi, sebagaimana telah disebutkan, template adalah alat standar yang sangat nyaman yang menikmati dukungan browser yang baik.
Dukungan browser HTML untuk browser modernTemplate bermanfaat dalam dan dari dirinya sendiri, tetapi kemampuannya diungkapkan sepenuhnya saat digunakan dengan elemen kustom. Elemen khusus adalah topik untuk bahan yang terpisah, dan sekarang, untuk memahami apa yang terjadi, cukup untuk mempertimbangkan bahwa
customElement
browser
customElement
memungkinkan pemrogram untuk menggambarkan tag HTML mereka sendiri dan menentukan bagaimana elemen yang dibuat dengan tag ini akan terlihat di layar.
Tetapkan komponen web yang menggunakan templat kami sebagai konten untuk DOM bayangannya. Sebut elemen baru ini
<my-paragraph>
:
customElements.define('my-paragraph', class extends HTMLElement { constructor() { super(); let template = document.getElementById('my-paragraph'); let templateContent = template.content; const shadowRoot = this.attachShadow({mode: 'open'}).appendChild(templateContent.cloneNode(true)); } });
Hal yang paling penting untuk diperhatikan adalah bahwa kami melampirkan klon dari konten template yang dibuat menggunakan metode
Node.cloneNode () ke root shadow.
Karena kami melampirkan konten template ke DOM bayangan, kami dapat menyertakan beberapa informasi gaya dalam template di elemen
<style> , yang kemudian akan dienkapsulasi dalam elemen pengguna. Keseluruhan skema ini tidak akan berfungsi seperti yang diharapkan jika Anda bekerja dengan DOM reguler, bukan Shadow DOM.
Misalnya, templat dapat dimodifikasi sebagai berikut dengan memasukkan informasi gaya di dalamnya:
<template id="my-paragraph"> <style> p { color: white; background-color: #666; padding: 5px; } </style> <p>Paragraph content. </p> </template>
Sekarang elemen pengguna yang kami jelaskan dapat digunakan pada halaman web biasa sebagai berikut:
<my-paragraph></my-paragraph>
Slot
Template HTML memiliki beberapa kelemahan, yang utama adalah bahwa template tersebut berisi markup statis, yang tidak memungkinkan, misalnya, menampilkan konten variabel tertentu dengan bantuan mereka agar dapat bekerja dengan mereka dengan cara yang sama seperti mereka bekerja dengan HTML standar pola. Di sinilah tag
<slot>
masuk.
Slot dapat dianggap sebagai placeholder yang memungkinkan Anda untuk memasukkan kode HTML Anda sendiri dalam templat. Ini memungkinkan Anda untuk membuat templat HTML universal dan kemudian membuatnya dapat disesuaikan dengan menambahkan slot ke dalamnya.
Lihatlah bagaimana template di atas akan terlihat menggunakan
<slot>
:
<template id="my-paragraph"> <p> <slot name="my-text">Default text</slot> </p> </template>
Jika konten slot tidak ditentukan saat elemen dimasukkan dalam markup, atau jika browser tidak mendukung bekerja dengan slot, elemen
<my-paragraph>
hanya akan memasukkan konten standar dari
Default text
.
Untuk mengatur isi slot, Anda harus memasukkan kode HTML dengan atribut
slot
di elemen
<my-paragraph>
, yang nilainya setara dengan nama slot tempat Anda ingin menempatkan kode ini.
Seperti sebelumnya, bisa ada apa saja. Sebagai contoh:
<my-paragraph> <span slot="my-text">Let's have some different text!</span> </my-paragraph>
Elemen yang dapat ditempatkan dalam slot disebut elemen
Slotable .
Harap perhatikan bahwa pada contoh sebelumnya kami menambahkan elemen
<span>
ke slot, itu yang disebut elemen slotted. Ini memiliki atribut
slot
yang diberikan nilai
my-text
, yaitu nilai yang sama yang digunakan dalam atribut
name
slot yang dijelaskan dalam templat.
Setelah memproses markup di atas, browser akan membuat pohon DOM rata:
<my-paragraph> #shadow-root <p> <slot name="my-text"> <span slot="my-text">Let's have some different text!</span> </slot> </p> </my-paragraph>
Perhatikan elemen
#shadow-root
. Ini hanya indikator keberadaan DOM Shadow.
Stilisasi
Komponen yang menggunakan teknologi Shadow DOM dapat ditata secara umum, mereka dapat menentukan gaya mereka sendiri, atau memberikan kait dalam bentuk
properti CSS kustom yang memungkinkan pengguna komponen untuk menimpa gaya default.
▍ Gaya yang dijelaskan dalam komponen
Isolasi CSS adalah salah satu fitur paling luar biasa dari teknologi Shadow DOM. Yaitu, kita berbicara tentang hal berikut:
- Selektor CSS dari halaman tempat komponen terkait tidak mempengaruhi apa yang ada di dalamnya.
- Gaya yang dijelaskan dalam komponen tidak mempengaruhi halaman. Mereka terisolasi dalam elemen host.
Selektor CSS yang digunakan di dalam bayangan DOM berlaku secara lokal untuk konten komponen. Dalam praktiknya, ini berarti kemampuan untuk menggunakan kembali pengidentifikasi dan nama kelas yang sama dalam komponen yang berbeda dan tidak perlu khawatir tentang konflik nama. Penyeleksi CSS sederhana juga berarti kinerja yang lebih baik untuk solusi di mana mereka digunakan.
Lihatlah elemen
#shadow-root
, yang mendefinisikan beberapa gaya:
#shadow-root <style> #container { background: white; } #container-items { display: inline-flex; } </style> <div id="container"></div> <div id="container-items"></div>
Semua gaya di atas adalah lokal untuk
#shadow-root
.
Selain itu, Anda dapat menggunakan tag
<link>
untuk menyertakan style sheet eksternal di
#shadow-root
. Gaya seperti itu juga akan bersifat lokal.
▍Pseudoclass: host
The
:host
pseudo-
:host
memungkinkan Anda untuk mengakses elemen yang mengandung pohon DOM bayangan dan gaya elemen ini:
<style> :host { display: block; } </style>
Menggunakan
:host
pseudo-
:host
, ingat bahwa aturan halaman induk memiliki prioritas lebih tinggi daripada yang ditentukan dalam elemen menggunakan kelas pseudo ini. Ini memungkinkan pengguna untuk mengganti gaya komponen host yang ditentukan di dalamnya dari luar. Selain itu,:
:host
pseudo-
:host
hanya berfungsi dalam konteks elemen root shadow, Anda tidak dapat menggunakannya di luar pohon shadow DOM.
Bentuk fungsional pseudo-class ,:
:host(<selector>)
, memungkinkan Anda untuk mengakses elemen host jika cocok dengan elemen
<selector>
ditentukan. Ini adalah cara yang bagus untuk memungkinkan komponen merangkum perilaku yang merespons tindakan pengguna atau perubahan dalam keadaan komponen, dan memungkinkan Anda untuk mendesain node internal berdasarkan pada komponen host:
<style> :host { opacity: 0.4; } :host(:hover) { opacity: 1; } :host([disabled]) { background: grey; pointer-events: none; opacity: 0.4; } :host(.pink) > #tabs { color: pink; } </style>
▍Topik dan elemen dengan pseudo-class: host-context (<selector>)
The
:host-context(<selector>)
pseudo
:host-context(<selector>)
cocok dengan elemen host jika elemen tersebut atau leluhurnya cocok dengan elemen
<selector>
ditentukan.
Kasing yang umum digunakan untuk fitur ini adalah menata elemen dengan tema. Misalnya, tema sering digunakan dengan menetapkan kelas yang sesuai ke
<html>
atau
<body>
:
<body class="lightheme"> <custom-container> … </custom-container> </body>
The
:host-context(.lightheme)
pseudo
:host-context(.lightheme)
akan diterapkan ke
<fancy-tabs>
jika elemen ini adalah turunan dari
.lightteme
:
:host-context(.lightheme) { color: black; background: white; }
Konstruk
:host-context()
mungkin berguna untuk menerapkan tema, tetapi untuk tujuan ini lebih baik menggunakan kait menggunakan
properti CSS khusus .
▍ Menata elemen host komponen dari luar
Elemen host komponen dapat ditata secara eksternal menggunakan nama tag-nya sebagai pemilih:
custom-container { color: red; }
Gaya eksternal lebih diutamakan daripada gaya yang ditentukan dalam bayangan DOM.
Misalkan pengguna membuat pemilih berikut:
custom-container { width: 500px; }
Itu akan menimpa aturan yang didefinisikan dalam komponen itu sendiri:
:host { width: 300px; }
Dengan menggunakan pendekatan ini, Anda hanya dapat menyesuaikan dgn mode komponen itu sendiri. Bagaimana menyesuaikan dgn mode struktur internal komponen? Properti CSS khusus digunakan untuk tujuan ini.
▍Membuat kait gaya menggunakan properti CSS khusus
Pengguna dapat menyesuaikan gaya struktur internal komponen jika pembuat komponen memberi mereka gaya kait menggunakan
properti CSS kustom .
Pendekatan ini didasarkan pada mekanisme yang mirip dengan yang digunakan saat bekerja dengan
<slot>
, tetapi, dalam hal ini, berlaku untuk gaya.
Pertimbangkan sebuah contoh:
<style> custom-container { margin-bottom: 60px; - custom-container-bg: black; } </style> <custom-container background>…</custom-container>
Inilah yang ada di dalam pohon DOM bayangan:
:host([background]) { background: var( - custom-container-bg, #CECECE); border-radius: 10px; padding: 10px; }
Dalam hal ini, komponen menggunakan hitam sebagai warna latar belakang, karena itu adalah pengguna yang menentukannya. Jika tidak, warna latar belakang akan menjadi
#CECECE
.
Sebagai pembuat komponen, Anda bertanggung jawab untuk memberi tahu penggunanya properti CSS spesifik apa yang dapat mereka gunakan. Pertimbangkan ini bagian dari antarmuka terbuka komponen Anda.
JavaScript API untuk bekerja dengan slot
API Shadow DOM menyediakan kemampuan untuk bekerja dengan slot.
▍Event slotchange
Acara
slotchange
dinaikkan ketika node yang ditempatkan di slot berubah. Misalnya, jika pengguna menambahkan atau menghapus node anak di Light DOM:
var slot = this.shadowRoot.querySelector('#some_slot'); slot.addEventListener('slotchange', function(e) { console.log('Light DOM change'); });
Untuk melacak jenis perubahan lainnya di Light DOM, Anda dapat menggunakan
MutationObserver
di konstruktor elemen. Baca lebih lanjut tentang ini di
sini .
▍ Metode yang ditugaskanNode ()
Metode yang
assignedNodes()
dapat berguna jika Anda perlu tahu elemen mana yang dikaitkan dengan slot. Memanggil metode
slot.assignedNodes()
memungkinkan Anda untuk mengetahui elemen mana saja yang ditampilkan oleh slot. Menggunakan opsi
{flatten: true}
memungkinkan Anda untuk mendapatkan konten standar slot (ditampilkan jika tidak ada node yang terpasang padanya).
Pertimbangkan sebuah contoh:
<slot name='slot1'><p>Default content</p></slot>
Bayangkan slot ini terletak di komponen
<my-container>
.
Mari kita lihat berbagai kegunaan untuk komponen ini, dan apa yang akan dikembalikan ketika metode
assignedNodes()
dipanggil.
Dalam kasus pertama, kami menambahkan konten kami sendiri ke slot:
<my-container> <span slot="slot1"> container text </span> </my-container>
Dalam hal ini, panggilan yang
assignedNodes()
akan mengembalikan
[ container text ]
. Perhatikan bahwa nilai ini adalah array node.
Dalam kasus kedua, kami tidak mengisi slot dengan konten kami sendiri:
<my-container> </my-container>
Panggilan yang
assignedNodes()
akan mengembalikan array kosong -
[]
.
Namun, jika Anda melewatkan parameter
{flatten: true}
ke metode ini, maka memanggilnya untuk elemen yang sama akan mengembalikan konten default-nya:
[ Default content ]
[ Default content ]
[ Default content ]
Selain itu, untuk mengakses elemen di dalam slot, Anda dapat memanggil
assignedNodes()
untuk memberi tahu Anda slot komponen mana yang ditugaskan untuk elemen Anda.
Model acara
Mari kita bicara tentang apa yang terjadi ketika suatu peristiwa yang muncul di pohon bayangan DOM muncul. Tujuan acara diatur dengan mempertimbangkan enkapsulasi yang didukung oleh teknologi Shadow DOM. Ketika suatu acara dialihkan, itu tampak seolah-olah berasal dari komponen itu sendiri, dan bukan dari elemen internal, yang terletak di pohon bayangan DOM dan merupakan bagian dari komponen ini.
Berikut adalah daftar peristiwa yang dilewatkan dari pohon bayangan DOM (perilaku ini bukan karakteristik dari beberapa peristiwa):
- Acara Fokus:
blur
, focus
, focus
, focus
. - Acara Mouse s:
click
, dblclick
, mousedown
, mouseenter
, mousemove
, dan lainnya. - Acara Roda:
wheel
. - Input Events:
beforeinput
input
, input
. - Acara Keyboard:
keydown
, keyup
. - Acara Komposisi:
compositionstart
, compositionupdate
, compositionend
. - Seret Peristiwa:
drag
dragstart
, drag
, dragend
, drop
, dan sebagainya.
Acara khusus
Peristiwa pengguna secara default tidak meninggalkan pohon bayangan DOM. Jika Anda ingin memicu suatu acara, dan Anda ingin meninggalkan Shadow DOM, Anda harus memberikannya dengan
bubbles: true
parameter
bubbles: true
dan
composed: true
. Ini adalah bagaimana panggilan acara seperti itu terlihat:
var container = this.shadowRoot.querySelector('#container'); container.dispatchEvent(new Event('containerchanged', {bubbles: true, composed: true}));
Dukungan untuk browser Shadow DOM
Untuk mengetahui apakah browser mendukung teknologi Shadow DOM, Anda dapat memeriksa keberadaan
attachShadow
:
const supportsShadowDOMV1 = !!HTMLElement.prototype.attachShadow;
Berikut adalah informasi tentang bagaimana berbagai browser mendukung teknologi ini.
Dukungan untuk teknologi Shadow DOM di browserRingkasan
Pohon DOM bayangan tidak berperilaku seperti pohon DOM biasa. Secara khusus, menurut penulis bahan ini, di perpustakaan
SessionStack ini dinyatakan dalam kerumitan prosedur untuk melacak perubahan DOM, informasi tentang yang diperlukan untuk mereproduksi apa yang terjadi dengan halaman. Yaitu,
MutationObserver
digunakan untuk melacak perubahan. Dalam kasus ini, pohon bayangan DOM tidak meningkatkan peristiwa
MutationObserver
dalam lingkup global, yang mengarah pada kebutuhan untuk menggunakan pendekatan khusus untuk bekerja dengan komponen yang menggunakan Shadow DOM.
, - Shadow DOM, , , , .
Pembaca yang budiman! -, Shadow DOM?
