DEV Community

Cover image for Web Components, o que são e como criar (parte 1)
Gabriel José
Gabriel José

Posted on • Updated on

Web Components, o que são e como criar (parte 1)

Essa é a primeira parte de uma série de tutoriais sobre Web Components. Nesse tutorial veremos o que são Web Components e como fazer um.

Resumidamente um Web Component é uma tag customizada, podendo ser uma nova tag, um aprimoramento de uma tag já existente ou de outra tag customizada. Nós utilizamos da API customElements para criar esses elementos customizados.

Definindo um novo elemento

A API customElements possuí um método define que é utilizado para definir um novo elemento. Ele recebe 3 parâmetros, mas por enquanto vamos mexer somente com os 2 primeiros. O primeiro parâmetro é o nome da tag e o segundo parâmetro é uma classe que herde de HTMLElement.

class MyText extends HTMLElement {}
customElements.define('my-text', MyText)

// Ou usando uma classe anônima
customElements.define('my-text', class extends HTMLElement {})
Enter fullscreen mode Exit fullscreen mode

Repare que o nome da tag está todo em minúsculo e possuí um "-", não é por coincidência, existem algumas regras a seguir:

  • Deve possuir no mínimo um "-"(traço).
  • Além do "-" o único carácter especial aceito é "_"(underscore).
  • Possuir somente letras minúsculas.
  • Deve iniciar com no mínimo uma letra.
  • Todas as tags devem possuir um fechamento (<my-tag></my-tag>), pois o HTML só permite tags auto fechadas, como o meta ou img, para algumas tags específicas.

O motivo dessas regras é para que o analisador do HTML possa distinguir entre elementos customizados e elementos normais. Além disso, garante que não ocorra problemas com futuras tags que forem adicionados ao HTML.

Definindo o conteúdo do componente

Para definir o conteúdo HTML de um elemento você pode simplesmente adicionar o valor ao seu atributo innerHTML. Lembrando que seu componente possuí acesso a todos os tipos de propriedades gerais dos elementos HTML, como innerHTML, getAttribute, children, entre outros...

Vamos criar um index.html com o seguinte conteúdo:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <link rel="shortcut icon" href="data:image/x-icon;" type="image/x-icon">
  <title>Web components</title>
</head>
<body>
  <my-text></my-text>

  <script>
    class MyText extends HTMLElement {
      constructor() {
        super()
        this.innerHTML = '<h2>Meu Texto</h2>'
      }
    }

    customElements.define('my-text', MyText)
  </script>
</body>
</html>
Enter fullscreen mode Exit fullscreen mode

Será possível ver escrito Meu Texto na página do navegador.

Nesse mesmo código mova o conteúdo da tag script para um arquivo separado e vamos continuar por nele.

O conteúdo desse elemento pode ser facilmente estilizado com CSS. No caso do h2 do my-text seria selecionando o elemento de dentro da tag, por exemplo, my-text h2 ou my-text > h2. Depois veremos mais sobre o uso de CSS com Web Components, mas por enquanto, assim funciona.

Usando Templates

Nós também podemos utilizar das tags template para gerar o conteúdo HTML dos componentes. Caso você não conheça sobre as tags de template, basicamente, tudo que for inserido dentro da tag não será interpretado pelo analisador do HTML. Contudo, esse conteúdo pode ser replicado inúmeras vezes usando a propriedade content.

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <link rel="shortcut icon" href="data:image/x-icon;" type="image/x-icon">
  <title>Web components</title>
</head>
<body>
  <my-text></my-text>

    <template>
    <h2>Meu Texto</h2>
  </template>

  <script src="js/main.js"></script>
</body>
</html>
Enter fullscreen mode Exit fullscreen mode
const template = document.querySelector('template')

class MyText extends HTMLElement {
  constructor() {
    super()
    this.append(template.content.cloneNode(true))
  }
}

customElements.define('my-text', MyText)
Enter fullscreen mode Exit fullscreen mode

Utilizando o método cloneNode de content é possível copiar todo o conteúdo interno do template.

Estendendo elementos

Além de criar novos elementos a API customElements também nós permite estender elementos previamente criados.

class MyTitle extends MyText {
  constructor() {
    super()
  }
}

customElements.define('my-title', MyTitle)
Enter fullscreen mode Exit fullscreen mode

Com o código acima podemos estender o elemento my-text que criamos anteriormente. Note que ao inserir <my-title></my-title> no html veremos o mesmo resultado de my-text. O Elemento my-title herda tudo que foi inserido em my-text e usando de princípios da programação orientada a objetos você pode alterar a forma como o elemento se comporta.

Estendendo elementos HTML nativos

Além de criar novos elementos a partir de outros, você também pode criar elementos a partir dos elementos já existentes no HTML.

É bem simples de se implementar e pode ser bastante útil dependendo do seu objetivo.

Para se criar um elemento dessa maneira é necessário que o elemento herde da interface DOM correta. Ao criar um elemento novo herdamos da interface HTMLElement e dependendo da tag que você deseja herdar a interface será diferente. Como por exemplo, um button usa a interface HTMLButtonElement, um p usa a interface HTMLParagraphElement:

class MyParagraph extends HTMLParagraphElement {
  constructor() {
    super()
    this.innerHTML = 'Meu parágrafo!!!'
  }
}

customElements.define('my-parag', MyParagraph, { extends: 'p' })
Enter fullscreen mode Exit fullscreen mode
<p is="my-parag"></p>
Enter fullscreen mode Exit fullscreen mode

Repare em dois detalhes, primeiro que usamos o terceiro parâmetro do customElements.define no qual é um objeto que recebe a opção extends em que inserimos qual a tag que desejamos estender e segundo que não colocamos <my-parag></my-parag> e sim usando o atributo is direto na tag p.

Gerando elementos programaticamente

Você pode gerar um elemento customizado usando a classe em que ele foi definido.

const myText = new MyText()
Enter fullscreen mode Exit fullscreen mode

E você pode conseguir acesso a essa classe através do método get do customElements. Ele recebe um parâmetro que será o nome do elemento previamente definido.

const MyText = customElements.get('my-text')
const myText = new MyText()
Enter fullscreen mode Exit fullscreen mode

No caso de elementos que estendem elementos nativos do HTML, eles podem ser criados das mesmas maneiras já mostradas ou usando document.createElement e será necessário passar um segundo parâmetro indicando que ele é um elemento customizado.

const myParagraph = document.createElement('p', { is: 'my-parag' })
Enter fullscreen mode Exit fullscreen mode

Referências

https://developers.google.com/web/fundamentals/web-components/customelements

Conclusão

Esse é o básico quando se trata da criação de Web Components. Ainda há bastante a se falar sobre então fique atento as próximas partes. Espero que tenha gostado e qualquer dúvida pode deixar um comentário, no mais até logo!!!

Top comments (0)