No desenvolvimento web, compreneder como os eventos se comportam na árvore DOM é fundamental. A propagação de eventos, especificamente o event bubbling (ou borbulhamento de eventos), ocorre quando um evento disparado em um elemento filho é subsequentemente propagado para seus ancestrais. Se um elemento não interceptar ou cancelar a propagação, o evento "sobe" pela hierarquia até atingir o objeto document (ou window em alguns contextos).
Demonstração Prática do Bubbling
Considere a seguinte estrutura HTML com três níveis de aninhamento. Cada elemento possui um manipulador para o evento de clique:
<html lang="pt-BR">
<head>
<meta charset="UTF-8">
<title>Hierarquia de Eventos</title>
<style>
.wrapper-external { padding: 30px; border: 2px dashed blue; }
.wrapper-internal { padding: 20px; border: 2px dashed green; }
</style>
</head>
<body>
<div class="wrapper-external" onclick="console.log('Nível externo acionado');">
<div class="wrapper-internal" onclick="console.log('Nível intermediário acionado');">
<a id="target-link" href="https://developer.mozilla.org" onclick="console.log('Nível interno acionado');">Executar Ação</a>
</div>
</div>
</body>
</html>
Ao interagir com o link "Executar Ação", a sequência de execução no console será:
- Nível interno acionado
- Nível intermediário acionado
- Nível externo acionado
- Redriecionamento para a URL especificada no
href.
Isso ilustra perfeitamente o bubbling: a interação ocorreu no elemento mais profundo (target-link), mas os elementos pais também reagiram ao mesmo evento.
Interrompendo a Propagação (stopPropagation)
Para evitar que o evento continue subindo na árvore DOM e acionando os listeners dos elementos pais, utilizamos o método event.stopPropagation(). Isso isola a execução apenas ao elemento que originou o evento.
document.addEventListener('DOMContentLoaded', function() {
var linkElement = document.querySelector('#target-link');
linkElement.addEventListener('click', function(e) {
// Impede que o evento chegue aos divs pais
e.stopPropagation();
console.log('Ação interna processada sem propagar.');
});
});
Com essa implementação, ao clicar no link, apenas a mensagem do nível interno será exibida no console, seguida pelo redirecionamento padrão da página.
Cancelando o Comportamento Padrão (preventDefault)
Em alguns cenários, o objetivo não é bloquear a propagação, mas sim anular a ação nativa do elemento, como o envio de um formulário ou o redirecionamento de um link. Para isso, aplicamos event.preventDefault().
document.addEventListener('DOMContentLoaded', function() {
var linkElement = document.querySelector('#target-link');
linkElement.addEventListener('click', function(e) {
// Bloqueia o redirecionamento do href
e.preventDefault();
console.log('Comportamento padrão cancelado.');
});
});
Neste caso, a propagação continua ocorrendo normalmente (os consoles dos divs pais serão executados), mas o navegador não realizará a navegação para a URL do link, mantendo o usuário na página atual.