Article image
Arthur Vieira
Arthur Vieira13/01/2024 16:55
Compartilhe

Como criar tags HTML personalizadas (Custom Elements).

  • #HTML
  • #JavaScript
  • #TypeScript

Opa, tudo bom? Você sabia que é possível criar tags personalizadas no HTML de uma maneira bem simples?

Primeiro, vamos por partes.

Quais os benefícios de criar tags personalizadas?

  • Imagine que você tenha que criar uma aplicação que tenha vários cards, que contêm um título, descrição, link para a matéria, entre outros atributos
<body>
  <div class="card">
      <h1>Card Title</h1>
      <p>
          Lorem ipsum dolor, sit amet consectetur adipisicing elit. Sunt temporibus dicta minima adipisci delectus! Ad sed facilis dolorem! Quam in quidem voluptate voluptatem, saepe dolorem vero nemo ipsa, soluta error.
      </p>
      <a href="">Link of content</a>
  </div>
</body>
  • Concorda que, com o tempo, haverá diversas divs iguais, em que apenas o que muda é seu conteúdo?
<body>
  <div class="card">
      <h1>Card Title</h1>
      <p>
          Lorem ipsum dolor, sit amet consectetur adipisicing elit. Sunt temporibus dicta minima adipisci delectus! Ad sed facilis dolorem! Quam in quidem voluptate voluptatem, saepe dolorem vero nemo ipsa, soluta error.
      </p>
      <a href="">Link of content</a>
  </div>
  <div class="card">
      <h1>Card Title</h1>
      <p>
          Lorem ipsum dolor, sit amet consectetur adipisicing elit. Sunt temporibus dicta minima adipisci delectus! Ad sed facilis dolorem! Quam in quidem voluptate voluptatem, saepe dolorem vero nemo ipsa, soluta error.
      </p>
      <a href="">Link of content</a>
  </div>
</body>
  • Quem já usa tecnologias com Angular, React, Vue... sabe onde eu quero chegar: na componentização!
  • Para dar uma maior legibilidade ao código, criamos componentes, que são nada mais do que trechos de código que se repetem, como o card acima, os encapsulando

Mas para fazer isso, precisamos entender alguns conceitos base

  • O HTML é composto pela DOM (Document Object Model), onde fica tudo que vemos, ou seja, as tags, como buttons, inputs...
  • Para criar as tags personalidas/componentes, vamos mexer na Shadow DOM, ela é uma espécie do DOM, porém ela cria uma outra árvore de elementos dentro da DOM
  • A DOM em si é um document a qual são inseridas todas as tags que escrevemos, criando o que chamamos de árvore, porém, quando mexemos na Shadow DOM, criamos uma espécie de outra árvore particular que não interfere na árvore principal da DOM

Criando sua tag personalizada

  • Em um arquivo JavaScript ou Typescript, precisamos criar uma classe que extenda alguma tag em específico ou o próprio HTMLElement de uma vez, no caso do nosso card, como não queremos apenas uma tag vamos herdar todo o HTMElement
//index.ts
class CardComponent extends HTMLElement {
  constructor(){
      super();

      const shadow: ShadowRoot = this.attachShadow({ mode: 'open' });
  }
}


customElements.define('card-component', CardComponent);
  • A variável shadow é a nossa Shadow DOM, usamos o attachShadow para dizer que queremos mexer nela, por isso passamos o mode como opencustomElements.define
  • O customElements.define serve para definir o nome da tag personalizada e qual tag é essa, respectivamente
  • Nosso componente é composto por um h1, um p e um a, então vamos criar eles
//index.ts
class CardComponent extends HTMLElement {
  constructor(){
      super();

      const shadow: ShadowRoot = this.attachShadow({ mode: 'open' });

      const title: HTMLHeadElement = document.createElement('h1');
      const content: HTMLParagraphElement = document.createElement('p');
      const link: HTMLAnchorElement = document.createElement('a');
  }
}
customElements.define('card-component', CardComponent);
  • Após isso, precisamos colocá-los na nossa Shadow DOM
//index.ts
class CardComponent extends HTMLElement {
  constructor(){
      super();

      const shadow: ShadowRoot = this.attachShadow({ mode: 'open' });

      const title: HTMLHeadElement = document.createElement('h1');
      const content: HTMLParagraphElement = document.createElement('p');
      const link: HTMLAnchorElement = document.createElement('a');

      shadow.appendChild(title);
      shadow.appendChild(content);
      shadow.appendChild(link);
  }
  
}

customElements.define('card-component', CardComponent);
  • Agora, com o arquivo linkado ao seu HTML, podemos usar a tag, porém, ainda não terá nenhum efeito
<body>	
  <card-component></card-component>
</body>
  • Mas como faço para passar o título e os demais conteúdos? Simples, por atributos
  • Ainda na classe da tag podemos pegar o valor de atributos e colocá-los como conteúdo das nossas tags, observe
//index.ts
class CardComponent extends HTMLElement {
  constructor(){
      super();

      const shadow: ShadowRoot = this.attachShadow({ mode: 'open' });

      const title: HTMLHeadElement = document.createElement('h1');
      const content: HTMLParagraphElement = document.createElement('p');
      const link: HTMLAnchorElement = document.createElement('a');

      title.innerText = this.getAttribute('title')!;
      content.innerText = this.getAttribute('content')!;
      link.setAttribute('href', this.getAttribute('url')!);
      link.innerText = "Link da matéria";

      shadow.appendChild(title);
      shadow.appendChild(content);
      shadow.appendChild(link);
  }	
}

customElements.define('card-component', CardComponent);
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title></title>
</head>
<body>
  <card-component
      title="Título do card"
      content="Lorem ipsum dolor sit amet, consectetur adipisicing elit."
      url="#"
  ></card-component>
</body>


<script src='./index.js'></script>
</html>
  • Nosso componente está pronto e pode ser reutilizado quantas vezes forem necessárias
  • Quer colocar css nele? Basta criar uma tag de estilo e colocar na Shadow DOM também
class CardComponent extends HTMLElement {
  constructor(){
      super();

      const shadow: ShadowRoot = this.attachShadow({ mode: 'open' });

      const title: HTMLHeadElement = document.createElement('h1');
      const content: HTMLParagraphElement = document.createElement('p');
      const link: HTMLAnchorElement = document.createElement('a');
      const styles: HTMLStyleElement = document.createElement('style');

      title.innerText = this.getAttribute('title')!;
      content.innerText = this.getAttribute('content')!;
      link.setAttribute('href', this.getAttribute('url')!);
      link.innerText = "Link da matéria";

      styles.innerText = `
          h1 {
              color: red;
          }
      `;

      shadow.appendChild(title);
      shadow.appendChild(content);
      shadow.appendChild(link);
      shadow.appendChild(styles);
  }
}
customElements.define('card-component', CardComponent);
  • Pronto está tudo pronto. Obrigado por ter ficado até o final. Até a próxima!

Fontes

Sobre mim:

Nome: Arthur Levy

Formação atual: técnico em Desenvolvimento de Sistemas - ETE Ginásio Pernambucano.

Compartilhe
Comentários (2)
Arthur Vieira
Arthur Vieira - 13/01/2024 17:20

Obrigado, Lendro Silva!


Leandro Silva
Leandro Silva - 13/01/2024 17:08

Show de bola, parabéns!!!