Shadow DOM i JavaScript
Den här artikeln förklarar 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>
Förstå Shadow DOM
Shadow DOM
är en kraftfull funktion inom Web Components-standarden som möjliggör inkapsling av stilar och DOM-struktur inom komponenter. Denna funktion förhindrar störningar mellan stilar och skript i komponenter och huvuddokumentet.
Shadow DOM
i JavaScript
Shadow DOM
ger ett sätt att skapa ett avgränsat DOM-träd kopplat till ett vanligt DOM-element. Detta skuggträd är isolerat från det övergripande dokumentet, där externa stilar och skript inte påverkar det och dess interna stilar och skript inte läcker ut.
Till exempel, om du skapar en anpassad knappkomponent med Shadow DOM
, kommer dess stilar inte att störa andra element på sidan. På samma sätt kommer element med samma klassnamn inte att orsaka konflikter.
Vanligt HTML-innehåll utanför Shadow DOM
kallas för Light DOM
.
Fördelar med Shadow DOM
-
Inkapsling
Shadow DOM
separerar stil och funktionalitet, vilket förhindrar konflikter med globala stilar och skript.
-
Återanvändbarhet
- Komponenter byggda med
Shadow DOM
kan återanvändas i olika projekt utan att man behöver oroa sig för stilkonflikter.
- Komponenter byggda med
-
Underhållbarhet
- Inkapsling gör komponentens logik och stil självständiga, vilket gör felsökning och underhåll enklare.
Skapa Shadow DOM
För att använda Shadow DOM
måste du fästa en skuggrot till ett HTML-element. Här är ett enkelt exempel:.
1// Select the host element
2const hostElement = document.querySelector('#shadow-host');
3
4// Attach a shadow root
5const shadowRoot = hostElement.attachShadow({ mode: 'open' });
Förklaring
Den här koden innehåller följande element:.
-
Värdelement
- Ett vanligt DOM-element där shadow root är kopplat (i det här fallet,
#shadow-host
).
- Ett vanligt DOM-element där shadow root är kopplat (i det här fallet,
-
Shadow Root
- Roten av skuggträdet som skapas med hjälp av
attachShadow
.
- Roten av skuggträdet som skapas med hjälp av
-
Läge
- I
open
-läge kan extern JavaScript komma åt shadow root viaelement.shadowRoot
. Å andra sidan tillåter inteclosed
-läget åtkomst.
- I
Stilhantering inom Shadow DOM
Shadow DOM
har sitt eget stilområde. Stilar som definieras inom skuggan trädet gäller endast för elementen inom det trädet. Här är ett exempel:.
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`;
Även om det finns konflikterande stilar i huvuddokumentet påverkar de inte paragrafen inuti 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`;
- Paragrafen inuti
Shadow DOM
förblir grön, medan den utanför är röd.
Händelser inom Shadow DOM
Händelser inom Shadow DOM
liknar vanliga DOM-händelser men kan bete sig annorlunda vad gäller spridning på grund av kapsling.
Här är ett exempel:.
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 klickas på aktiveras båda lyssnarna, vilket demonstrerar beteendet för händelsebubbling.
- När en händelse som uppstår inne i
Shadow DOM
bubblar upp tillLight DOM
, skrivs händelsenstarget
om till värdelementet istället för den ursprungliga källan.- I det här exemplet är
event.target
inne iShadow DOM
det faktiskabutton
-elementet, men utanförShadow DOM
ersätts det med värd-div
-elementet.
- I det här exemplet är
Shadow DOM
och anpassade element
Shadow DOM
och anpassade element är nyckelkomponenter i Web Components
. De är teknologier som används för att skapa återanvändbara och kapslade 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);
Huvuddokumentet innehåller HTML som detta:.
1<my-card></my-card>
- Genom att använda
Shadow DOM
inom anpassade element kan du skapa återanvändbara komponenter som är motståndskraftiga mot stilkonflikter. I den här koden skapas en tagg med namnetmy-card
och kopplas till klassenMyCard
.<p>
-elementet inutimy-card
påverkas inte av externa stilar och visas alltid i blått.
Slots: Fördelning av Light DOM
-innehåll
Slots gör det möjligt att projicera Light DOM
-innehåll in i Shadow DOM
. Här är ett exempel:.
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);
Huvuddokumentet innehåller HTML som detta:.
1<my-element>
2 <h3 slot="header">Header Content</h1>
3 <p slot="content">Main Content</p>
4</my-element>
slot
-elementet inutiShadow DOM
visar detLight DOM
-innehåll som har motsvarandeslot
-attribut.
Slutsats
Shadow DOM
är ett viktigt verktyg för att bygga robusta, återanvändbara och underhållbara webbkomponenter. Genom att kapsla in stilar och funktioner minskar det risken för konflikter och förenklar hantering av kodbasen.
Du kan följa med i artikeln ovan med hjälp av Visual Studio Code på vår YouTube-kanal. Vänligen kolla även in YouTube-kanalen.