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
- https://developer.mozilla.org/
- Desenvolvimento WEB com Angular da DIO
Sobre mim:
Nome: Arthur Levy
Formação atual: técnico em Desenvolvimento de Sistemas - ETE Ginásio Pernambucano.