Shadow DOM в TypeScript

Shadow DOM в TypeScript

Эта статья объясняет Shadow DOM в TypeScript.

Мы подробно объясним всё, начиная с основ Shadow DOM и заканчивая его практическим применением, а также предоставим практические примеры кода.

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>

Подробное объяснение и практическое пошаговое руководство по Shadow DOM

Shadow DOM — это один из ключевых компонентов веб-компонентов. Он создает инкапсулированное дерево DOM, отделяя стили и структуру компонента от внешней среды. Здесь мы дадим подробное объяснение основ Shadow DOM и его практического применения, дополненное примерами кода.

Что такое Shadow DOM?

Shadow DOM — это технология веб-стандартов с следующими характеристиками.

  1. Инкапсуляция

    Shadow DOM отделяет внутреннюю структуру DOM компонента от внешней среды. Другие стили и скрипты не вмешиваются, что улучшает возможность повторного использования.

  2. Независимая область стилей

    Стили внутри Shadow DOM не влияют на внешний CSS. Аналогично, внешние стили не применяются внутри Shadow DOM.

  3. Изолированное дерево DOM

    Shadow DOM существует как отдельное дерево от обычного DOM, с ограниченным доступом из родительского DOM.

Основы использования Shadow DOM

Следующий код является первым примером использования 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`;
  • Браузер отобразит синий текст: 'Это внутри Shadow DOM!'. Стиль этого текста не зависит от внешнего CSS.

Основные шаги работы с Shadow DOM

Чтобы использовать Shadow DOM, как показано в этом коде, используйте метод attachShadow в JavaScript. Ниже приведены основные шаги:.

  1. Создание пользовательских элементов Пользовательский элемент — это определённый пользователем тег, который вы можете создать в дополнение к стандартным HTML-тегам. На этом этапе вы создаёте класс, который расширяет HTMLElement, как, например, класс MyElement, чтобы браузер мог распознавать его как новый тег. Зарегистрировав созданный класс с помощью customElements.define(), вы сможете использовать его в HTML как пользовательский тег.

  2. Присоединение Shadow DOM Выполнив this.attachShadow() внутри пользовательского элемента, вы можете создать Shadow DOM.

  3. Добавление HTML и CSS внутри Shadow DOM Внутри Shadow DOM вы можете определять собственную структуру HTML и стили. Например, задав HTML и CSS свойству innerHTML, вы можете придать компоненту независимый вид и поведение, не зависящие от внешних CSS или HTML. Это позволяет создавать инкапсулированные компоненты.

Режимы Shadow DOM: open и closed

У Shadow DOM есть два режима: open и closed.

  • Открытый режим: Свойство shadowRoot, привязанное к Shadow DOM, доступно извне.
  • Закрытый режим: Свойство shadowRoot, привязанное к Shadow DOM, недоступно извне.

Ниже приведен пример кода, показывающий различия между двумя режимами.

 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が出力される
  • Выбор режима closed делает свойство shadowRoot недоступным.

Инкапсуляция стилей с использованием Shadow DOM

С помощью Shadow DOM вы можете полностью инкапсулировать стили внутри своих компонентов.

Следующий пример демонстрирует разделение глобальных стилей и стилей внутри 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`;
  • p элементы внутри Shadow DOM не подвержены воздействию глобальных стилей и имеют свои собственные уникальные стили.

Практический пример Shadow DOM: Пользовательская подсказка

Далее мы представляем пример создания пользовательской подсказки с использованием 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`;
  • Этот код создает пользовательскую подсказку и отображает стилизованную подсказку при наведении.

Резюме

Shadow DOM — это ключевая технология для Веб-компонентов, обеспечивающая инкапсуляцию DOM и области стилей. Здесь мы рассмотрели основы Shadow DOM, его использование, различия режимов, инкапсуляцию стилей и практические примеры. Используя всё это, вы можете создавать повторно используемые и надёжные компоненты.

Вы можете следовать этой статье, используя Visual Studio Code на нашем YouTube-канале. Пожалуйста, также посмотрите наш YouTube-канал.

YouTube Video