Shadow DOM i JavaScript
Denne artikel 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 af Shadow DOM
Shadow DOM
er en kraftfuld funktion i Web Components-standarden, der muliggør indkapsling af styles og DOM-struktur inden for komponenter. Denne funktion forhindrer forstyrrelser mellem styles og scripts fra komponenter og hoveddokumentet.
Shadow DOM
i JavaScript
Shadow DOM
giver en måde at oprette et afgrænset DOM-træ, der er knyttet til et almindeligt DOM-element. Dette skyggetræ er isoleret fra det samlede dokument, hvor eksterne styles og scripts ikke påvirker det, og de interne styles og scripts heller ikke lækker ud.
For eksempel, hvis du opretter en brugerdefineret knappekomponent ved hjælp af Shadow DOM
, vil dens styles ikke forstyrre andre elementer på siden. Ligeledes vil elementer med samme klassed navn ikke komme i konflikt.
Det almindelige HTML-indhold uden for Shadow DOM
kaldes Light DOM
.
Fordele ved Shadow DOM
-
Indkapsling
Shadow DOM
adskiller stil og funktionalitet, hvilket forhindrer konflikter med globale stilarter og scripts.
-
Genanvendelighed
- Komponenter bygget med
Shadow DOM
kan genbruges på tværs af forskellige projekter uden at bekymre sig om stilkonflikter.
- Komponenter bygget med
-
Vedligeholdelse
- Indkapsling gør komponentens logik og stil selvstændig, hvilket gør fejlfinding og vedligeholdelse lettere.
Oprettelse af Shadow DOM
For at bruge Shadow DOM
skal du knytte en shadow root til et HTML-element. Her er et simpelt 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 kode indeholder følgende elementer:.
-
Værtelement
- Et almindeligt DOM-element, som shadow root er knyttet til (i dette tilfælde
#shadow-host
).
- Et almindeligt DOM-element, som shadow root er knyttet til (i dette tilfælde
-
Shadow Root
- Roden af skyggetræet, oprettet med
attachShadow
.
- Roden af skyggetræet, oprettet med
-
Tilstand
- I
open
-tilstand kan ekstern JavaScript få adgang til shadow root viaelement.shadowRoot
. Derimod tilladerclosed
-tilstand ikke adgang.
- I
Styling inden for Shadow DOM
Shadow DOM
har sit eget stilområde. Stile defineret inden for skyggetræet gælder kun for elementerne i det træ. 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`;
Selvom der er modstridende stilarter i hoveddokumentet, påvirker de ikke paragrafen inde i shadow tree.
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`;
- Paragraffen inde i
Shadow DOM
forbliver grøn, mens den eksterne er rød.
Hændelser inden for Shadow DOM
Hændelser inden for Shadow DOM
ligner almindelige DOM-hændelser, men kan opføre sig anderledes med hensyn til forplantning på grund af indkapsling.
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, udløses begge lyttere, hvilket demonstrerer adfærden ved hændelsesbobling.
- Når en hændelse, der opstår inde i
Shadow DOM
, bobler op tilLight DOM
, bliver hændelsenstarget
omskrevet til værtselementet i stedet for den oprindelige kilde.- I dette eksempel er
event.target
inde iShadow DOM
det faktiskebutton
-element, men udenforShadow DOM
erstattes det med værtensdiv
-element.
- I dette eksempel er
Shadow DOM
og brugerdefinerede elementer
Shadow DOM
og brugerdefinerede elementer er nøglekomponenter i Web Components
. De er teknologier, der bruges til at skabe genanvendelige og indkapslede 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 indeholder HTML som dette:.
1<my-card></my-card>
- Ved at bruge
Shadow DOM
i brugerdefinerede elementer kan du bygge genanvendelige komponenter, der er modstandsdygtige over for stil-konflikter. I denne kode oprettes et tag ved navnmy-card
, som associeres med klassenMyCard
.<p>
-elementet inde imy-card
påvirkes ikke af eksterne stilarter og vises altid i blå.
Slots: Distribuering af Light DOM
-indhold
Slots giver dig mulighed for at projicere Light DOM
-indhold ind 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 indeholder 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 inden iShadow DOM
viserLight DOM
-indhold, der har den tilsvarendeslot
-attribut.
Konklusion
Shadow DOM
er et vigtigt værktøj til at bygge robuste, genanvendelige og vedligeholdelsesvenlige webkomponenter. Ved at indkapsle stilarter og funktionalitet reduceres potentialet for konflikter, og administrationen af kodebasen forenkles.
Du kan følge med i ovenstående artikel ved hjælp af Visual Studio Code på vores YouTube-kanal. Husk også at tjekke YouTube-kanalen.