Shadow DOM i JavaScript
Denne artikkelen forklarer Shadow DOM i 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 & 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>
Forståelse av Shadow DOM
Shadow DOM
er en kraftig funksjon i Web Components-standarden som muliggjør kapsling av stiler og DOM-struktur innenfor komponenter. Denne funksjonen forhindrer interferens av stiler og skript mellom komponenter og hoveddokumentet.
Shadow DOM
i JavaScript
Shadow DOM
gir en måte å opprette et avgrenset DOM-tre tilknyttet et vanlig DOM-element. Dette skyggedokumentet er isolert fra det totale dokumentet, slik at eksterne stiler og skript ikke påvirker det, og interne stiler og skript lekker ikke ut.
For eksempel, hvis du lager en tilpasset knappkomponent ved hjelp av Shadow DOM
, vil dens stiler ikke forstyrre andre elementer på siden. På samme måte vil elementer med samme klassenavn ikke komme i konflikt.
Vanlig HTML-innhold utenfor Shadow DOM
kalles Light DOM
.
Fordeler med Shadow DOM
-
Innkapsling
Shadow DOM
skiller stil og funksjonalitet, og forhindrer konflikter med globale stiler og skript.
-
Gjenbrukbarhet
- Komponenter bygget med
Shadow DOM
kan gjenbrukes på ulike prosjekter uten å bekymre seg for stilkonflikter.
- Komponenter bygget med
-
Vedlikeholdbarhet
- Innkapsling gjør komponentens logikk og stil selvstendig, noe som gjør feilsøking og vedlikehold enklere.
Opprette Shadow DOM
For å bruke Shadow DOM
, må du knytte en skyggerot til et HTML-element. Her er et enkelt eksempel:.
1// Select the host element
2const hostElement = document.querySelector('#shadow-host');
3
4// Attach a shadow root
5const shadowRoot = hostElement.attachShadow({ mode: 'open' });
Forklaring
Denne koden inneholder følgende elementer:.
-
Vertselement
- Et vanlig DOM-element som shadow root er festet til (i dette tilfellet,
#shadow-host
).
- Et vanlig DOM-element som shadow root er festet til (i dette tilfellet,
-
Shadow Root
- Roten til skyggetreet, opprettet med
attachShadow
.
- Roten til skyggetreet, opprettet med
-
Modus
- I
open
-modus kan ekstern JavaScript få tilgang til shadow root viaelement.shadowRoot
. På den andre siden tillater ikkelukket
modus tilgang.
- I
Stilsetting innenfor Shadow DOM
Shadow DOM
har sitt eget stilomfang. Stiler definert i shadow-treet gjelder kun for elementer innenfor det treet. Her er et eksempel:.
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`;
Selv om det finnes stilkonflikter i hoveddokumentet, påvirker de ikke paragrafen inne i shadow-treet.
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`;
- Paragrafen inne i
Shadow DOM
forblir grønn, mens den eksterne er rød.
Hendelser i Shadow DOM
Hendelser i Shadow DOM
ligner vanlige DOM-hendelser, men kan oppføre seg annerledes med hensyn til propagasjon på grunn av kapsling.
Her er et eksempel:.
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});
- Når knappen klikkes, aktiveres begge lytterne, noe som demonstrerer oppførselen til hendelsesbobling.
- Når en hendelse som starter inne i
Shadow DOM
bobler opp tilLight DOM
, blir hendelsenstarget
omskrevet til vertselementet i stedet for den opprinnelige kilden.- I dette eksempelet er
event.target
inne iShadow DOM
det faktiskebutton
-elementet, men utenforShadow DOM
blir det erstattet med vertselementetdiv
.
- I dette eksempelet er
Shadow DOM
og egendefinerte elementer
Shadow DOM
og egendefinerte elementer er nøkkelkomponenter i Web Components
. De er teknologier som brukes til å lage gjenbrukbare og innkapslede UI-komponenter.
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);
Hoveddokumentet inneholder HTML som dette:.
1<my-card></my-card>
- Ved å bruke
Shadow DOM
inne i egendefinerte elementer kan du lage gjenbrukbare komponenter som er motstandsdyktige mot stilkonflikter. I denne koden opprettes en tagg kaltmy-card
og knyttes til klassenMyCard
. Elementet<p>
inne imy-card
påvirkes ikke av eksterne stiler og vises alltid i blått.
Slots: Distribuere Light DOM
-innhold
Slots lar deg projisere Light DOM
-innhold inn i Shadow DOM
. Her er et eksempel:.
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);
Hoveddokumentet inneholder HTML som dette:.
1<my-element>
2 <h3 slot="header">Header Content</h1>
3 <p slot="content">Main Content</p>
4</my-element>
slot
-elementet inne iShadow DOM
viserLight DOM
-innhold som har tilsvarendeslot
-attributt.
Konklusjon
Shadow DOM
er et viktig verktøy for å bygge robuste, gjenbrukbare og vedlikeholdbare webkomponenter. Ved å kapsle inn stiler og funksjonalitet reduserer den potensialet for konflikter og forenkler styring av kodebasen.
Du kan følge med på artikkelen ovenfor ved å bruke Visual Studio Code på vår YouTube-kanal. Vennligst sjekk ut YouTube-kanalen.