Shadow DOM dalam JavaScript

Shadow DOM dalam JavaScript

Artikel ini menerangkan tentang Shadow DOM dalam JavaScript.

YouTube Video

javascript-html-shadow-dom.html
  1<!DOCTYPE html>
  2<html lang="en">
  3<head>
  4  <meta charset="UTF-8">
  5  <title>JavaScript &amp; HTML</title>
  6  <style>
  7    * {
  8        box-sizing: border-box;
  9    }
 10
 11    body {
 12        margin: 0;
 13        padding: 1em;
 14        padding-bottom: 10em;
 15        font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
 16        background-color: #f7f9fc;
 17        color: #333;
 18        line-height: 1.6;
 19    }
 20
 21    .container {
 22        max-width: 800px;
 23        margin: 0 auto;
 24        padding: 1em;
 25        background-color: #ffffff;
 26        border: 1px solid #ccc;
 27        border-radius: 10px;
 28        box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05);
 29    }
 30
 31    h1, h2 {
 32        font-size: 1.2rem;
 33        color: #007bff;
 34        margin-top: 0.5em;
 35        margin-bottom: 0.5em;
 36        border-left: 5px solid #007bff;
 37        padding-left: 0.6em;
 38        background-color: #e9f2ff;
 39    }
 40
 41    button {
 42        display: block;
 43        margin: 1em auto;
 44        padding: 0.75em 1.5em;
 45        font-size: 1rem;
 46        background-color: #007bff;
 47        color: white;
 48        border: none;
 49        border-radius: 6px;
 50        cursor: pointer;
 51        transition: background-color 0.3s ease;
 52    }
 53
 54    button:hover {
 55        background-color: #0056b3;
 56    }
 57
 58    #output {
 59        margin-top: 1em;
 60        background-color: #1e1e1e;
 61        color: #0f0;
 62        padding: 1em;
 63        border-radius: 8px;
 64        min-height: 200px;
 65        font-family: Consolas, monospace;
 66        font-size: 0.95rem;
 67        overflow-y: auto;
 68        white-space: pre-wrap;
 69    }
 70
 71    .highlight {
 72        outline: 3px solid #ffc107; /* yellow border */
 73        background-color: #fff8e1;  /* soft yellow background */
 74        transition: background-color 0.3s ease, outline 0.3s ease;
 75    }
 76
 77    .active {
 78        background-color: #28a745; /* green background */
 79        color: #fff;
 80        box-shadow: 0 0 10px rgba(40, 167, 69, 0.5);
 81        transition: background-color 0.3s ease, box-shadow 0.3s ease;
 82    }
 83  </style>
 84</head>
 85<body>
 86    <div class="container">
 87        <h2>HTML Sample</h2>
 88        <div id="content"></div>
 89        <div id="shadow-host">Shadow Root Element</div>
 90        <my-card></my-card>
 91    </div>
 92
 93    <div class="container">
 94        <h1>JavaScript Console</h1>
 95        <button id="executeBtn">Execute</button>
 96        <div id="output"></div>
 97    </div>
 98
 99    <div>
100        <h2>Slot Sample</h2>
101        <my-element>
102            <h3 slot="header">Header Content</h1>
103            <p slot="content">Main Content</p>
104        </my-element>
105    </div>
106
107    <script>
108        // Override console.log to display messages in the #output element
109        (function () {
110            const originalLog = console.log;
111            console.log = function (...args) {
112                originalLog.apply(console, args);
113                const output = document.getElementById('output');
114                output.textContent += args.map(String).join(' ') + '\n';
115            };
116        })();
117
118        document.getElementById('executeBtn').addEventListener('click', () => {
119            // Prevent multiple loads
120            if (document.getElementById('externalScript')) return;
121
122            const script = document.createElement('script');
123            script.src = 'javascript-html-shadow-dom.js';
124            script.id = 'externalScript';
125            //script.onload = () => console.log('javascript-html-shadow-dom.js loaded and executed.');
126            //script.onerror = () => console.log('Failed to load javascript-html-shadow-dom.js.');
127            document.body.appendChild(script);
128        });
129    </script>
130</body>
131</html>

Memahami Shadow DOM

Shadow DOM adalah ciri yang kuat dalam piawaian Komponen Web yang membolehkan pengkapsulan gaya dan struktur DOM dalam komponen. Ciri ini menghalang gangguan gaya dan skrip antara komponen dan dokumen utama.

Shadow DOM dalam JavaScript

Shadow DOM menyediakan cara untuk mencipta pokok DOM yang terhad yang dikaitkan dengan elemen DOM biasa. Pokok bayangan ini diasingkan daripada dokumen keseluruhan, di mana gaya dan skrip luaran tidak mempengaruhinya, dan gaya serta skrip dalaman tidak tersebar keluar.

Sebagai contoh, jika anda mencipta komponen butang tersuai menggunakan Shadow DOM, gayanya tidak akan mengganggu elemen lain di halaman itu. Begitu juga, elemen dengan nama kelas yang sama tidak akan bertembung.

Kandungan HTML biasa di luar Shadow DOM dirujuk sebagai Light DOM.

Manfaat Shadow DOM

  1. Pengkapsulan

    • Shadow DOM memisahkan gaya dan fungsi, mengelakkan konflik dengan gaya dan skrip global.
  2. Boleh Digunakan Semula

    • Komponen yang dibina dengan Shadow DOM boleh digunakan semula dalam pelbagai projek tanpa risau tentang konflik gaya.
  3. Penyelenggaraan

    • Pengkapsulan menjadikan logik dan gaya komponen berdikari, memudahkan penyahpepijatan dan penyelenggaraan.

Membuat Shadow DOM

Untuk menggunakan Shadow DOM, anda perlu melampirkan akar bayangan kepada elemen HTML. Berikut ialah contoh ringkas:.

1// Select the host element
2const hostElement = document.querySelector('#shadow-host');
3
4// Attach a shadow root
5const shadowRoot = hostElement.attachShadow({ mode: 'open' });

Penjelasan

Kod ini merangkumi elemen-elemen berikut:.

  1. Elemen Hos

    • Elemen DOM biasa yang dilekatkan shadow root (dalam kes ini, #shadow-host).
  2. Akar Shadow

    • Akar bagi pohon shadow yang dicipta menggunakan attachShadow.
  3. Mod

    • Dalam mod open, JavaScript luar boleh mengakses shadow root melalui element.shadowRoot. Sebaliknya, mod closed tidak membenarkan akses.

Penggayaan dalam Shadow DOM

Shadow DOM mempunyai skop gaya tersendiri. Gaya yang ditentukan dalam shadow tree hanya terpakai pada elemen dalam pokok tersebut. Berikut adalah contohnya:.

1// Add content to the shadow root
2shadowRoot.innerHTML = `
3    <style>
4        p {
5            color: green;
6        }
7    </style>
8    <p>Scoped style inside Shadow DOM.</p>
9`;

Walaupun terdapat gaya yang bercanggah dalam dokumen utama, ia tidak menjejaskan perenggan di dalam pohon shadow.

1const content = document.getElementById('content');
2content.innerHTML = `
3    <style>
4        p {
5            color: red;
6        }
7    </style>
8    <p>This is in the main DOM.</p>
9`;
  • Perenggan di dalam Shadow DOM kekal berwarna hijau, manakala yang di luar berwarna merah.

Acara dalam Shadow DOM

Acara dalam Shadow DOM adalah serupa dengan acara DOM biasa tetapi mungkin berkelakuan berbeza dari segi penyebaran kerana enkapsulasi.

Berikut adalah contohnya:.

 1// Add an event listener inside Shadow DOM
 2shadowRoot.innerHTML = `
 3    <div id="button-container">
 4        <button id="shadow-button">Click Me</button>
 5    </div>
 6`;
 7
 8shadowRoot.querySelector('#shadow-button').addEventListener('click', (event) => {
 9    console.log('Button : Button clicked inside Shadow DOM');
10    console.log(event.target);
11});
12
13shadowRoot.querySelector('#button-container').addEventListener('click', (event) => {
14    console.log('Container : Button clicked inside Shadow DOM');
15    console.log(event.target);
16});
17
18hostElement.addEventListener('click', (event) => {
19    console.log('Event bubbled to the host element');
20    console.log(event.target);
21});
22
23document.addEventListener('click', (event) => {
24    console.log('Document listener');
25    console.log(event.target);
26});
  • Apabila butang ditekan, kedua-dua pendengar diaktifkan, menunjukkan tingkah laku gelembung acara.
  • Apabila satu acara yang berasal dari dalam Shadow DOM naik ke Light DOM, target acara tersebut akan ditulis semula kepada elemen hos dan bukannya sumber asal.
    • Dalam contoh ini, event.target di dalam Shadow DOM adalah elemen button sebenar, tetapi di luar Shadow DOM, ia digantikan dengan elemen hos div.

Shadow DOM dan Elemen Tersuai

Shadow DOM dan elemen tersuai adalah komponen utama dalam Web Components. Ia adalah teknologi yang digunakan untuk mencipta komponen UI yang boleh diguna semula dan terenkapsulasi.

 1class MyCard extends HTMLElement {
 2    constructor() {
 3        super();
 4        const shadow = this.attachShadow({ mode: 'open' });
 5        shadow.innerHTML = `
 6        <style>
 7            p {
 8                color: blue;
 9            }
10        </style>
11        <p>I'm inside shadow DOM</p>
12        `;
13    }
14}
15
16customElements.define('my-card', MyCard);

Dokumen utama mengandungi HTML seperti berikut:.

1<my-card></my-card>
  • Dengan menggunakan Shadow DOM di dalam elemen tersuai, anda boleh membina komponen yang boleh diguna semula dan tahan terhadap konflik gaya. Dalam kod ini, satu tag bernama my-card dicipta dan dihubungkan dengan kelas MyCard. Elemen <p> di dalam my-card tidak terpengaruh oleh gaya luar dan sentiasa dipaparkan dalam warna biru.

Slot: Mengagihkan Kandungan Light DOM

Slot membolehkan anda memproyeksikan kandungan Light DOM ke dalam Shadow DOM. Berikut adalah contohnya:.

 1class MyElement extends HTMLElement {
 2    constructor() {
 3        super();
 4        const shadow = this.attachShadow({ mode: 'open' });
 5
 6        shadow.innerHTML = `
 7        <style>
 8            .container {
 9                border: 2px solid #ccc;
10                padding: 16px;
11                border-radius: 8px;
12                font-family: sans-serif;
13            }
14            .header {
15                font-size: 1.2em;
16                color: darkblue;
17                margin-bottom: 8px;
18            }
19            .content {
20                font-size: 1em;
21                color: #333;
22            }
23        </style>
24        <div class="container">
25            <div class="header">
26                <slot name="header"></slot>
27            </div>
28            <div class="content">
29                <slot name="content"></slot>
30            </div>
31        </div>
32        `;
33    }
34}
35
36customElements.define('my-element', MyElement);

Dokumen utama mengandungi HTML seperti berikut:.

1<my-element>
2    <h3 slot="header">Header Content</h1>
3    <p slot="content">Main Content</p>
4</my-element>
  • Elemen slot di dalam Shadow DOM memaparkan kandungan Light DOM yang mempunyai atribut slot yang sepadan.

Kesimpulan

Shadow DOM adalah alat penting untuk membina komponen web yang kukuh, boleh digunakan semula, dan mudah diselenggara. Dengan mengenkapsulasi gaya dan fungsi, ia mengurangkan potensi konflik dan mempermudah pengurusan kod asas.

Anda boleh mengikuti artikel di atas menggunakan Visual Studio Code di saluran YouTube kami. Sila lihat juga saluran YouTube kami.

YouTube Video