Como Funcionam o Event Bubbling e o Event Delegation?
Event bubbling, ou propagação, refere-se a como um evento "bubbles up" para objetos pai quando acionado. Por exemplo, considere este código:
<p>
<span>Click me~!</span>
</p>
O elemento p aqui seria considerado o pai do elemento span.
Quando você clica no elemento span, como foi instruído, o elemento span se torna o alvo de um evento click. Esse evento, no entanto, também sobe para o elemento pai – o elemento p pode receber e consumir esse evento conforme necessário.
Mas o que isso realmente significa? Bem, você poderia anexar um listener de evento ao elemento p:
const p = document.querySelector("p");
p.addEventListener("click", (event) => {
console.log(event.target);
});
Então, quando você clicar no elemento span você verá o texto Click me~! registrado no console.
O evento se propaga para o elemento pai p, que o consome em um listener de evento para exibir o alvo do evento.
Note como o alvo ainda é o elemento span. Isso ocorre porque o elemento span recebeu o clique inicial.
Só para ter certeza de como as coisas estão funcionando, vamos expandir nosso código:
const p = document.querySelector("p");
const span = document.querySelector("span");
p.addEventListener("click", (event) => {
console.log("P listener: ");
console.log(event.target);
});
span.addEventListener("click", (event) => {
console.log("Span listener: ");
console.log(event.target);
});
Para te dar uma ideia de como o evento propaga, aqui está o que você verá no console após clicar no elemento span:
"Span listener: "
<span>Click me~!</span>
"P listener: "
<span>Click me~!</span>
Agora vamos ver o que acontece quando você impede a propagação de um evento com stopPropagation(). Chamaremos isso no listener de eventos do nosso span:
const p = document.querySelector("p");
const span = document.querySelector("span");
p.addEventListener("click", (event) => {
console.log("P listener: ");
console.log(event.target);
});
span.addEventListener("click", (event) => {
console.log("Span listener: ");
console.log(event.target);
event.stopPropagation();
});
E então clique novamente no nosso span:
"Span listener: "
<span>Click me~!</span>
Desta vez, não vemos nosso listener p ser acionado. O evento nunca é disparado para o elemento p, porque dissemos para ele parar a propagação enquanto estava sendo processado para o elemento filho span.
A delegação de eventos pode ser vista como o oposto. É o processo de pegar um evento capturado e delegá-lo para outro elemento.
Voltando ao nosso código, vamos atualizá-lo para que clicar em um elemento span o altere para vermelho:
const p = document.querySelector("p");
const span = document.querySelector("span");
p.addEventListener("click", (event) => {});
span.addEventListener("click", (event) => {
event.target.style.color = "red";
});
Mas e se você tiver vinte elementos span? Ou talvez você use JavaScript para criar mais elementos span dinamicamente?
Ao invés de ter que anexar um listener de evento a cada elemento span, você pode na verdade usar o listener no elemento p para todos eles. Em outras palavras, você pode delegar o tratamento dos cliques em span para o elemento pai p.
Nosso código agora pode parecer algo assim:
const p = document.querySelector("p");
p.addEventListener("click", (event) => {
event.target.style.color = "red";
});
Note como não temos mais nenhum listener anexado ao elemento span. Você delegou corretamente o tratamento de eventos para o elemento p. Mas funciona?
Vamos gerar alguns elementos span extras e ver:
<p>
<span>Click me~!</span>
<span>Click me~!</span>
<span>Click me~!</span>
<span>Click me~!</span>
</p>
Agora, cada vez que clicarmos em um span, o texto desse elemento ficará vermelho.
E assim, com um único event listener, permitimos corretamente que um evento click propague dos elementos span para o elemento pai p e delegamos a lógica para esse evento click ao elemento p.
A propagação e delegação de eventos podem ser um tópico complexo, especialmente quando você trabalha com elementos profundamente aninhados como tabelas. Você é incentivado a explorar isso mais a fundo e experimentar com parte do código que escrevemos aqui.Este módulo não possui perguntas. Marque como concluído.