# Event Capturing e Bubbling em JavaScript

> Entenda como funcionam Event Capturing e Bubbling em JavaScript. Aprenda a controlar a propagação de eventos e criar interfaces interativas eficientes.

URL: https://dpw.dev/miscelanea/eventos-javascript-capturing-bubbling/  
Publicado em: 2020-09-03  
Categoria: miscelanea  
Tags: javascript  
Autor: Tárcio Zemel

Manipular **eventos JavaScript** faz parte do dia-a-dia de qualquer programador front end e é tarefa banal.

Mas você saber como eventos em JavaScript realmente funcionam? 🤔

## Um exemplo de Eventos JavaScript

Talvez tudo o que você (pensava que) sabia sobre como eventos JavaScript funcionam esteja errado. Então, prepara-se para ter seu mundo abalado!

Para a demonstração, suponha uma hierarquia simples de elementos: 3 `div` aninhadas, cada uma com sua respectiva classe, “one”, “two” e “three”.

```html
<div class="one">
  <div class="two">
    <div class="three">
    </div>
  </div>
</div>
```

A aparência disso não é tão importante, mas, se quiser acompanhar mais visualmente, assista ao vídeo no início do artigo.

Usando um loop simples de [JavaScript](/categoria/javascript/), um evento de click será associado a cada uma dessas `div`.

```javascript
const $divs = document.querySelectorAll('div')

$divs.forEach(
  $div => $div.addEventListener('click', logClass)
)

function logClass() {
  console.log(this.classList.value)
}
```

Todas as `div` agora possuem um evento de `click` associado (para mostrar o nome de sua classe no console). Isso é muito importante para entender o restante.

Ao seu clicar na div mais interna, `.three`, o que você acha que vai ser logado no console?

- one
- two
- three

Acertou quem pensou:

```javascript
three
two
one
```

Exatamente, as 3 classes serão logadas!

Se você não entendeu o motivo disso, nesse ponto, é preciso explicar como as coisas realmente funcionam quando um evento JavaScript é disparado.

## Eventos JavaScript: como as coisas realmente funcionam

Quando um evento JavaScript é acionado, existem 2 fases associadas:

- **Capturing** (Captura)
- **Bubbling** (“Borbulhamento” ou Propagação)

### Fase de Capturing (Fase 1)

Por padrão, o evento de `click` (assim como quase todos os outros eventos em JavaScript) não acontece exatamente a partir do elemento que foi clicado.

Ao invés disso, o evento começa no nó root (`window`) e vai descendo por toda a hierarquia DOM até chegar no elemento em questão (o *target*).

Essa é a chamada **Fase de Capturing ou Captura** (ou Fase 1).

Nisso que ele vai passando por cada um dos elementos da hierarquia, caso haja algum evento do mesmo tipo respectivamente associado, **esse evento será disparado**.

### Fase de Bubbling (Fase 2)

Depois de percorrer todo esse caminho e finalmente encontrar o *target*, você acha que ele para? Não, não, não… Ele faz o caminho inverso pela mesma hierarquia até retornar ao elemento root (`window`).

Esse retorno é a chamada “Fase 2”, mais conhecida como **Fase de Bubbling** ou “Borbulhamento”.

Mas um outro nome é **Fase de Propagação**, em um certo sentido até mais condizente ao que acontece. O que é “Propagar”? É *difundir*; *divulgar*; *espalhar*… E é justamente isso que acontece.

Nesse caminho de volta ao root, novamente, se houver algum evento do mesmo tipo respectivamente associado a algum elemento da hierarquia, **esse evento será disparado**.

É por isso que, no exemplo, foi logado “three, two, one”, nessa ordem: dentro dessa hierarquia do aninhamento das `div`, na Fase de Bubbling primeiro ele disparou o evento da `div` mais interna, depois da central e, por fim, da mais externa.

## Opções para Event Listeners

Na sintaxe mais atual de JavaScript, é admitido um objeto como 3º parâmetro de `addEventListener` para informar opções relacionadas a esse *listener*.

Uma dessas opções é `capture: true`, que alteraria o código-exemplo para:

```javascript
$divs.forEach(
  $div => $div.addEventListener('click', logClass, {
    capture: true
  })
)
```

Essa opção significa que se está querendo trabalhar com o evento na Fase de Captura (como sugere o próprio nome da opção). Então, agora, ao se clicar na div mais interna, será logado:

```javascript
one
two
three
```
-->

Já que, na hierarquia, é disparado o evento `click` do elemento mais externo para o mais interno! 🤯

## Como interromper a propagação de um evento JavaScript

O JavaScript também oferece uma maneira de ter um controle mais acurado dessa dinâmica de eventos, permitindo **interromper a propagação de eventos**.

Alterando a opção `capture` para seu default `false`, faça-se um acréscimo à função que faz o log da classe:

```javascript
function logClass(e) {
  e.stopPropagation()

  console.log(this.classList.value)
}
```
-->

Com isso, ao se clicar em qualquer um dos elementos, ele vai logar unicamente a respectiva classe do que foi clicado, já que a propagação foi interrompida.

Então, diz aí: o que vai acontecer ao se usar o `stopPropagation()` juntamente com `capture: true`?

Para saber a resposta, assista o vídeo no início do artigo até o final. ;)

---

Fonte: [dpw - desenvolvimento para web](https://dpw.dev/) (pt-BR).
Guia para agentes: https://dpw.dev/llms.txt
Índice completo: https://dpw.dev/sitemap-index.xml
Feed: https://dpw.dev/rss.xml
