Shadow DOM em TypeScript

Shadow DOM em TypeScript

Este artigo explica o Shadow DOM em TypeScript.

Explicaremos cuidadosamente tudo, desde os fundamentos do Shadow DOM até seu uso prático, e forneceremos exemplos de código práticos.

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>

Explicação Detalhada e Guia Prático Passo a Passo sobre o Shadow DOM

Shadow DOM é um dos componentes principais dos Web Components. Ele cria uma árvore DOM encapsulada que separa o estilo e a estrutura do componente do exterior. Aqui, forneceremos uma explicação detalhada sobre os fundamentos do Shadow DOM até seus casos práticos de uso, junto com exemplos de código prático.

O que é Shadow DOM?

Shadow DOM é uma tecnologia padrão da web com as seguintes características.

  1. Encapsulamento

    Shadow DOM separa a estrutura DOM interna de um componente do exterior. Outros estilos e scripts não interferem, melhorando a reutilização.

  2. Escopo de Estilo Independente

    Estilos dentro do Shadow DOM não afetam o CSS externo. Da mesma forma, os estilos externos não são aplicados dentro do Shadow DOM.

  3. Árvore DOM Isolada

    Shadow DOM existe como uma árvore separada do DOM regular, com acesso restrito pelo DOM pai.

Uso Básico do Shadow DOM

O código a seguir é o primeiro exemplo utilizando 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`;
  • O navegador exibirá o texto azul: 'Isto está dentro do Shadow DOM!'. O estilo deste texto não é afetado por CSS externo.

Etapas básicas do Shadow DOM

Para usar o Shadow DOM, como mostrado neste código, você utiliza o método attachShadow em JavaScript. Abaixo estão os passos básicos:.

  1. Criando Elementos Personalizados Um elemento personalizado é uma tag definida pelo usuário que você pode criar além das tags padrão do HTML. Nesta etapa, você cria uma classe que estende HTMLElement, como a classe MyElement, preparando o navegador para reconhecê-la como uma nova tag. Ao registrar a classe criada com customElements.define(), você pode utilizá-la como uma tag personalizada no HTML.

  2. Anexando o Shadow DOM Ao executar this.attachShadow() dentro de um elemento personalizado, você pode criar um Shadow DOM.

  3. Adicionando HTML e CSS Dentro do Shadow DOM Dentro do Shadow DOM, você pode definir sua própria estrutura HTML e estilos. Por exemplo, ao definir HTML e CSS no innerHTML, você pode dar ao componente uma aparência e comportamento independentes, sem ser afetado por CSS ou HTML externos. Isso permite criar componentes encapsulados.

Modos do Shadow DOM: open e closed

O Shadow DOM possui dois modos: open e closed.

  • Modo Open: O shadowRoot conectado ao Shadow DOM pode ser acessado externamente.
  • Modo Closed: O shadowRoot conectado ao Shadow DOM não pode ser acessado externamente.

Abaixo está um exemplo de código que mostra as diferenças entre os dois modos.

 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が出力される
  • Escolher o modo closed torna a propriedade shadowRoot inacessível.

Encapsulamento de estilos usando Shadow DOM

Usando Shadow DOM, você pode encapsular completamente os estilos dentro de seus componentes.

O exemplo a seguir demonstra a separação de estilos globais e estilos dentro do 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`;
  • Os elementos p dentro do Shadow DOM não são afetados pelos estilos globais e têm seus próprios estilos exclusivos aplicados.

Exemplo prático de Shadow DOM: Tooltip personalizado

A seguir, apresentamos um exemplo de criação de um tooltip personalizado usando 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`;
  • Este código cria um tooltip personalizado e exibe um tooltip estilizado ao passar o mouse (hover).

Resumo

O Shadow DOM é uma tecnologia crucial para Web Components, fornecendo um DOM encapsulado e um escopo de estilo. Aqui, cobrimos os fundamentos do Shadow DOM, seu uso, diferenças de modos, encapsulamento de estilos e exemplos práticos. Aproveitando esses recursos, você pode criar componentes reutilizáveis e robustos.

Você pode acompanhar o artigo acima usando o Visual Studio Code em nosso canal do YouTube. Por favor, confira também o canal do YouTube.

YouTube Video