Web Components, atributos e métodos de reação (parte 2)
Gabriel José
Posted on March 2, 2021
Essa é a segunda parte da série de tutoriais sobre Web Components, não deixe de ver a primeira parte que mostro o que são e como criar Web Components. Nesse tutorial vamos ver como criar uma interface de programação(API) para nossos componentes e veremos como funcionam suas funções reação.
Definindo a API do elemento
Como comentado antes, assim que o elemento estende de HTMLElement
é garantido que ele herde a API DOM que existe em comum entre os elementos HTML, isso também significa que todo atributo/propriedade e métodos da classe farão parte dessa API DOM também.
Vamos, criar um <text-hider>
, um elemento simples que terá um X para esconder ou mostrar um texto.
class TextHider extends HTMLElement {
get show() {
return this.hasAttribute('show')
}
set show(value) {
if(typeof value !== 'boolean') {
throw new TypeError(
'text-hider "show" attribute only accepts boolean values'
)
}
if(value) {
this.setAttribute('show', '')
this.querySelector('[text]').innerText = 'Showing the text'
} else {
this.removeAttribute('show')
this.querySelector('[text]').innerText = ''
}
}
constructor() {
super()
this.innerHTML = `
<span>X</span>
<span text>${this.show ? 'Showing the text' : ''}</span>
`
this.querySelector('span').addEventListener('click', () => {
this.show = !this.show
})
}
}
customElements.define('text-hider', TextHider)
Repare no código acima que as funções getter e setter show
representam a propriedade show
que pode ser adicionada a tag text-hider
. Ela pode ser acessa de forma programática da seguinte maneira:
const textHider = new TextHider()
textHider.show = true
console.log(textHider.show) // true
Repare também em dois detalhes, um deles é que foi utilizado o método querySelector
atrelado ao this
, isso acontece porque o this
dentro da classe se refere diretamente ao elemento que estamos criando e que como dito antes ele possui toda a API DOM comum aos elementos HTML. O outro detalhe se encontra dentro do if
no método setter do atributo show
, em que alteramos o innerText do segundo elemento span dependendo se o valor recebido era verdadeiro ou falso, fazendo isso somos capazes de ter uma certa reatividade no elemento, fazendo com que ele reaja à toda vez em que o valor de show
é alterado.
Métodos de reação
Elementos customizados podem definir métodos de ciclo de vida especiais, que são executados em momentos específicos da sua existência. Eles são conhecidos como métodos de reação.
- constructor: chamado quando um novo elemento é instanciado ou aprimorado. Útil para definir estados iniciais, adicionar eventos e afins.
- connectedCallback: chamado quando o elemento é inserido dentro do DOM, sendo o light DOM ou o shadow DOM de outro elemento(depois vamos falar sobre light DOM e shadow DOM). Útil para rodar código preparatório ou que receba alguma condição externa ao entrar no DOM.
- disconnectedCallback: chamado quando o elemento é removido do DOM. Útil para rodar códigos de limpeza, como remoção de ouvintes de evento.
-
attributeChangedCallback: chamando quando algum atributo observado é adicionado, alterado ou removido. Esses atributos são listados no array retornado no método getter estático
observedAttributes
, logo mais falaremos sobre ele. Esse é o único método que recebe parâmetros, sendo o primeiro o nome do atributo alterado, o segundo sendo o valor antigo do atributo e o último sendo o novo valor. -
adoptedCallback: chamado quando o elemento é movido de documento. (por exemplo, quando alguém invoca
document.adoptNode(el)
).
Esses métodos de reação, são síncronos e serão imediatamente invocados quando as condições de invocação forem satisfeitas.
Não é necessário definir todos esses métodos, utilize deles quando fizer sentido.
class MeuComponente extends HTMLElement {
static get observedAttributes() {
return []
}
constructor() {
super()
}
connectedCallback() {...}
disconnectedCallback() {...}
attributeChangedCallback(name, oldValue, newValue) {...}
adoptedCallback() {...}
}
Propriedades e atributos
Como vimos antes podemos definir métodos para ter acesso aos atributos de um elemento de forma programática bem simples, além de ser um certo padrão de acesso aos atributos nos elementos HTML. Vamos usar uma div de exemplo alterando os atributos hidden
e id
:
div.id = 'my-id'
div.hidden = true
A atribuição pelo JS, é refletida no HTML:
<div id="my-id" hidden>
Isso pode ser chamado de "refletindo propriedades à atributos", lembrar desses detalhes é muito importante para ter a noção de que nosso elemento definido no JS está em sincronia com sua representação no DOM e isso pode até mesmo afetar estilizações que, por exemplo, usem seletores de atributos ([attribute]
).
Observando mudanças à atributos
Adicionar atributos a um elemento é uma forma comum de definir o estado inicial daquele elemento. Como vimos podemos adicionar um método attributeChangedCallback
para que nosso elemento reaja a mudança nos atributos, porém ele somente será invocado caso o nome do atributo esteja no array retornado por observedAttributes
e este método deve ser obrigatoriamente static get
.
static get observedAttributes() {
return ['attribute']
}
Isso é implementado dessa maneira por questão de performance, para que seu código não seja invocado de formas desnecessárias, como por exemplo, quando mudar o atributo class
e ser invocado attributeChangedCallback
.
Referências
https://developers.google.com/web/fundamentals/web-components/customelements
Conclusão
Essas são as formas como podemos manipular as reações dos elementos e seus atributos. O conteúdo dessa parte é de certa forma simples, porém eu aconselho muito a treinar bastante e ver como os elementos reagem para entender cada detalhe melhor. Espero que gostem e qualquer dúvida deixe um comentário e até logo!!!
Posted on March 2, 2021
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.