É muito comum você conhecer o event.target mas ainda não ter ouvido falar no event.currentTarget. Entenda a diferença.
Se você conhece o event.target, é tentador usar ele em situações como essa.
Imagine que você tem um ecommerce, e essa é sua página de produto:
Nela, o usuário vê a imagem de destaque à esquerda, e as minuatura do produto à direita. E digamos que você queira mudar a imagem de destaque, a cada clique nas miniaturas. Para isso, é preciso descobrir em qual cor o usuário clicou.
Infelizmente, usar o event.target aqui pode causar alguns probleminhas.
Veja o que pode acontecer.
O problema do event.target
Abaixo está a seção com as miniaturas das cores:
<button class="color-button" data-color="blue"> <img src="blue.png" /> </button> <button class="color-button" data-color="gray"> <img src="gray.png" /> </button> <button class="color-button" data-color="red"> <img src="red.png" /> </button> <button class="color-button" data-color="green"> <img src="green.png" /> </button> Perceba que cada botão possui um atributo data-color com a sua cor. Isso será importante daqui a pouco.
Agora veja como fica o script para adicionar um evento de clique nesses botões:
// Pegar os botões const colorButtons = document.querySelectorAll('.color-button'); // Iterar por eles, e adicionar um evento // que muda a foto principal com base na cor colorButtons.forEach(function(button) { button.addEventListener('click', changePictureByColor); // Criar a função do evento function changePictureByColor(event) { // ... } Até aqui tudo bem.
Agora, na função changePictureByColor você precisa descobrir qual foi a cor clicada.
Já que a cor está no atributo data-color de cada botão, basta pegar o seu valor:
function changePictureByColor(event) { const clickedColor = event.target.getAttribute('data-color'); // ... } Agora com a variável clickedColor em mãos, você pode seguir com a função e trocar a imagem em destaque.
Certo? Errado!
A sua função começa a estourar erros e mais erros... E após muito suor, você descobre que a variável clickedColor retorna null. Mas como?!
Como obter o elemento HTML alvo do evento
Console, eu escolho você!
Você então invoca uma chuva de console.log até descobrir que event.target não aponta para o botão. E sim para a imagem dentro do botão. E como a imagem não tem um atributo data-color, o caos começa.
Veja algumas formas de corrigir isso.
Adicionar o atributo data-color na imagem
Essa é a solução que gosto menos.
<button class="color-button"> <img src="blue.png" data-color="blue" /> </button> <button class="color-button"> <img src="gray.png" data-color="gray" /> </button> <button class="color-button"> <img src="red.png" data-color="red" /> </button> <button class="color-button"> <img src="green.png" data-color="green" /> </button> Isso porque, caso o usuário clique na pontinha do botão, ali onde a tag <img> já não existe mais, o event.target será o botão. E nesse caso, ele não possui o data-color.
Outra opção é...
Adicionar o atributo data-color na imagem e no botão
Antes eu estava de brincadeira. ESSA SIM é a solução que gosto menos.
Alguns dos motivos são:
- O dado fica repetido em mais de um lugar
- Caso existam outros elementos dentro de
<button>, todos eles precisariam do atributo.
Uma solução um pouco melhor (que usei por muito tempo) é...
Usar o método closest() do Javascript
Voltarei com o HTML original, com o data-color no botão:
<button class="color-button" data-color="blue"> <img src="blue.png" /> </button> <button class="color-button" data-color="gray"> <img src="gray.png" /> </button> <button class="color-button" data-color="red"> <img src="red.png" /> </button> <button class="color-button" data-color="green"> <img src="green.png" /> </button> Agora vou adicionar algumas linhas na função, para garantir que peguei o botão:
function changePictureByColor(event) { const clickedButton = event.target.closest('.color-button'); // pegar botão const clickedColor = clickedButton.getAttribute('data-color'); // pegar cor // ... } O método closest() recebe um seletor e retorna o primeiro elemento que corresponda a esse seletor. Porém em vez de buscar na página inteira, o método sobe na árvore HTML.
Então quando executo event.target.closest('.color-button'), os passos que a função closest() executa são os seguintes:
-
event.target(a imagem) possui a classecolor-button? Não, então executa novamente com o elemento pai da imagem -
<button class="color-button">possui a classecolor-button? Sim, então retorna ele - Fim
Caso chegue até o elemento raiz <html> e não encontre, retorna null.
Assim, tenho a certeza de que agora peguei o botão. Agora posso pegar a cor clicada e prosseguir.
Usei essa solução por muito tempo me achando o máximo. Até descobrir que posso...
Usar event.currentTarget em vez de event.target
E só isso!
function changePictureByColor(event) { const clickedColor = event.currentTarget.getAttribute('data-color'); // ... } Assim, a variável clickedColor sempre vai receber a cor presente no atributo data-color do botão.
Mas que magia aconteceu aqui?
O event.target aponta para o elemento que dispara o evento, ou seja, aquele que cliquei de fato. Isso pode ser o próprio botão, ou qualquer elemento dentro dele, como a imagem. Assim, em cada clique, event.target pode ser um elemento HTML diferente.
Já o event.currentTarget aponta sempre para o mesmo elemento. Aquele que foi atribuído ao addEventListener.
No exemplo do ecommerce que você acabou de ver, event.target e event.currentTarget apontam para elementos diferentes.
Callback
Como dito, a propriedade event.target aponta para o elemento que disparou o evento.
Já o event.currentTarget aponta para o elemento que possui o event listener associado a ele.
Fique atento para usar cada propriedade no momento certo.

Top comments (0)