Shadow DOM w TypeScript

Shadow DOM w TypeScript

Ten artykuł wyjaśnia Shadow DOM w TypeScript.

Dokładnie wyjaśnimy wszystko od podstaw Shadow DOM po jego praktyczne zastosowania i udostępnimy przykładowy kod do samodzielnego wypróbowania.

YouTube Video

typescript-html-shadow-dom.html
  1<!DOCTYPE html>
  2<html lang="en">
  3<head>
  4  <meta charset="UTF-8">
  5  <title>TypeScript &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>
 90
 91    <div class="container">
 92        <h1>JavaScript Console</h1>
 93        <button id="executeBtn">Execute</button>
 94        <div id="output"></div>
 95    </div>
 96
 97    <script>
 98        // Override console.log to display messages in the #output element
 99        (function () {
100            const originalLog = console.log;
101            console.log = function (...args) {
102                originalLog.apply(console, args);
103                const output = document.getElementById('output');
104                output.textContent += args.map(String).join(' ') + '\n';
105            };
106        })();
107
108        document.getElementById('executeBtn').addEventListener('click', () => {
109            // Prevent multiple loads
110            if (document.getElementById('externalScript')) return;
111
112            const script = document.createElement('script');
113            script.src = '/out/main.js';
114            script.id = 'externalScript';
115            //script.onload = () => console.log('typescript-html-shadow-dom.js loaded and executed.');
116            //script.onerror = () => console.log('Failed to load typescript-html-shadow-dom.js.');
117            document.body.appendChild(script);
118        });
119    </script>
120</body>
121</html>

Szczegółowe wyjaśnienie i praktyczny przewodnik krok po kroku po Shadow DOM

Shadow DOM to jeden z kluczowych elementów Web Components. Tworzy on zamknięte drzewo DOM, które oddziela styl i strukturę komponentu od otoczenia. Tutaj szczegółowo wyjaśnimy podstawy Shadow DOM i jego praktyczne zastosowania wraz z przykładami kodu do samodzielnych ćwiczeń.

Czym jest Shadow DOM?

Shadow DOM jest technologią standardową sieci web z następującymi cechami.

  1. Enkapsulacja

    Shadow DOM oddziela wewnętrzną strukturę DOM komponentu od otoczenia. Inne style i skrypty nie wpływają na komponent, co poprawia jego możliwości wielokrotnego użycia.

  2. Niezależny zakres stylów

    Style wewnątrz Shadow DOM nie wpływają na zewnętrzny CSS. Podobnie, zewnętrzne style nie mają zastosowania wewnątrz Shadow DOM.

  3. Izolowane drzewo DOM

    Shadow DOM istnieje jako odrębne drzewo od zwykłego DOM, z ograniczonym dostępem z nadrzędnego DOM.

Podstawowe zastosowanie Shadow DOM

Poniższy kod jest pierwszym przykładem użycia Shadow DOM.

 1class MyElement extends HTMLElement {
 2  constructor() {
 3    super();
 4
 5    // Attach Shadow DOM
 6    const shadowRoot = this.attachShadow({ mode: 'open' });
 7
 8    // Add HTML and CSS inside Shadow DOM
 9    shadowRoot.innerHTML = `
10      <style>
11        p {
12          color: blue;
13          font-size: 18px;
14        }
15      </style>
16      <p>This is inside Shadow DOM!</p>
17    `;
18  }
19}
20
21// Register the custom element
22customElements.define('my-element', MyElement);
23
24document.getElementById('content').innerHTML = `
25  <my-element></my-element>
26`;
  • Przeglądarka wyświetli niebieski tekst: 'This is inside Shadow DOM!'. Styl tego tekstu nie jest wpływany przez zewnętrzne CSS.

Podstawowe kroki dotyczące Shadow DOM

Aby używać Shadow DOM, tak jak pokazano w tym kodzie, używasz metody attachShadow w JavaScript. Poniżej znajdują się podstawowe kroki:.

  1. Tworzenie niestandardowych elementów Element niestandardowy to tag zdefiniowany przez użytkownika, który możesz utworzyć oprócz standardowych tagów HTML. Na tym etapie tworzysz klasę rozszerzającą HTMLElement, taką jak klasa MyElement, aby przygotować przeglądarkę do rozpoznania jej jako nowego tagu. Rejestrując utworzoną klasę za pomocą customElements.define(), możesz używać jej jako niestandardowego znacznika w HTML.

  2. Dołączanie Shadow DOM Wywołując this.attachShadow() wewnątrz elementu niestandardowego, możesz utworzyć Shadow DOM.

  3. Dodawanie HTML i CSS wewnątrz Shadow DOM W obrębie Shadow DOM możesz definiować własną strukturę HTML oraz style. Na przykład, ustawiając HTML i CSS do innerHTML, możesz nadać mu niezależny wygląd i zachowanie, bez wpływu zewnętrznych stylów CSS lub HTML. To pozwala na tworzenie kapsułkowanych komponentów.

Tryby Shadow DOM: otwarty i zamknięty

Shadow DOM ma dwa tryby: otwarty i zamknięty.

  • Tryb otwarty: shadowRoot przypisany do Shadow DOM może być dostępny zewnętrznie.
  • Tryb zamknięty: shadowRoot przypisany do Shadow DOM nie może być dostępny zewnętrznie.

Poniżej znajduje się przykład kodu pokazujący różnice między dwoma trybami.

 1class OpenElement extends HTMLElement {
 2  constructor() {
 3    super();
 4    this.attachShadow({ mode: 'open' }).innerHTML = `
 5      <p>Open Shadow DOM</p>
 6    `;
 7  }
 8}
 9
10class ClosedElement extends HTMLElement {
11  constructor() {
12    super();
13    this.attachShadow({ mode: 'closed' }).innerHTML = `
14      <p>Closed Shadow DOM</p>
15    `;
16  }
17}
18
19customElements.define('open-element', OpenElement);
20customElements.define('closed-element', ClosedElement);
21
22document.getElementById('content').innerHTML = `
23  <open-element></open-element>
24  <closed-element></closed-element>
25`;
26
27const openElement = document.querySelector('open-element') as OpenElement;
28console.log(openElement.shadowRoot); // ShadowRootが出力される
29
30const closedElement = document.querySelector('closed-element') as ClosedElement;
31console.log(closedElement.shadowRoot); // nullが出力される
  • Wybór trybu zamkniętego sprawia, że właściwość shadowRoot staje się niedostępna.

Enkapsulacja stylów za pomocą Shadow DOM

Korzystając z Shadow DOM, możesz całkowicie enkapsulować style wewnątrz swoich komponentów.

Poniższy przykład demonstruje oddzielenie stylów globalnych od stylów wewnątrz Shadow DOM.

 1class StyledElement extends HTMLElement {
 2  constructor() {
 3    super();
 4    const shadowRoot = this.attachShadow({ mode: 'open' });
 5
 6    shadowRoot.innerHTML = `
 7      <style>
 8        p {
 9          background-color: lightblue;
10          padding: 10px;
11          border: 1px solid blue;
12        }
13      </style>
14      <p>Shadow DOM Styled Content</p>
15    `;
16  }
17}
18
19customElements.define('styled-element', StyledElement);
20
21document.getElementById('content').innerHTML = `
22  <style>
23    p {
24      color: red;
25      font-weight: bold;
26    }
27  </style>
28
29  <styled-element></styled-element>
30`;
  • Elementy pznajdujące się wShadow DOM nie są objęte globalnymi stylami i mają zastosowane własne, unikalne style.

Praktyczny przykład Shadow DOM: niestandardowy dymek z podpowiedzią

Następnie wprowadzamy przykład tworzenia niestandardowego dymka z podpowiedzią za pomocą Shadow DOM.

 1class Tooltip extends HTMLElement {
 2  constructor() {
 3    super();
 4
 5    const shadowRoot = this.attachShadow({ mode: 'open' });
 6
 7    shadowRoot.innerHTML = `
 8      <style>
 9        :host {
10          position: relative;
11          display: inline-block;
12          cursor: pointer;
13        }
14
15        .tooltip {
16          visibility: hidden;
17          background-color: black;
18          color: white;
19          text-align: center;
20          padding: 5px;
21          border-radius: 5px;
22          position: absolute;
23          bottom: 125%;
24          left: 50%;
25          transform: translateX(-50%);
26          white-space: nowrap;
27        }
28
29        :host(:hover) .tooltip {
30          visibility: visible;
31        }
32      </style>
33      <slot></slot>
34      <div class="tooltip">Tooltip text</div>
35    `;
36  }
37}
38
39customElements.define('custom-tooltip', Tooltip);
40
41document.getElementById('content').innerHTML = `
42  <custom-tooltip>
43    Hover over me
44    <span slot="tooltip">This is a custom tooltip!</span>
45  </custom-tooltip>
46`;
  • Ten kod tworzy niestandardowy dymek z podpowiedzią i wyświetla go w określonym stylu po najechaniu kursorem.

Podsumowanie

Shadow DOM to kluczowa technologia dla komponentów sieciowych, zapewniająca enkapsulowany DOM i zakres stylów. Tutaj omówiliśmy podstawy Shadow DOM, jego zastosowanie, różnice między trybami, enkapsulację stylów i praktyczne przykłady. Wykorzystując te możliwości, możesz tworzyć wielokrotnego użytku i solidne komponenty.

Możesz śledzić ten artykuł, korzystając z Visual Studio Code na naszym kanale YouTube. Proszę również sprawdzić nasz kanał YouTube.

YouTube Video