O que é o evento borbulhando e capturando?

Qual é a diferença entre o evento a borbulhar e a capturar? Dos dois, Qual é o modelo mais rápido e melhor a usar?

Author: bjb568, 2011-01-06

5 answers

Borbulhar e capturar eventos são duas formas de propagação de eventos na API DOM HTML, quando um evento ocorre em um elemento dentro de outro elemento, e ambos os elementos registraram uma pega para esse evento. O modo de propagação do evento determina em qual ordem os elementos recebem o evento .

Com borbulhar, o evento é primeiro capturado e tratado pelo elemento mais interior e depois propagado para elementos exteriores. Com a captura, o evento é o primeiro capturada pelo elemento mais externo e propagada aos elementos interiores. A captura também é chamada de "trickling", o que ajuda a lembrar a ordem de propagação:
Para baixo, para cima.

Nos velhos tempos, o Netscape defendia a captura de eventos, enquanto a Microsoft promovia a borbulhagem de eventos. Ambos fazem parte da norma W3C Document Object Model Events (2000).

IE apenas o borbulhante de eventos , enquanto que IE9+ e todos os principais navegadores suportam ambos. Por outro lado, o desempenho da borbulhagem de eventos Pode ser ligeiramente inferior para Dom complexos.

Podemos usar o addEventListener(type, listener, useCapture) para registar os manipuladores de eventos tanto no modo borbulhante (por omissão) como no modo de captura. Para usar o modelo de captura passar o terceiro argumento como true.

Exemplo

<div>
    <ul>
        <li></li>
    </ul>
</div>

Na estrutura acima, assuma que ocorreu um evento click no elemento li.

Ao capturar o modelo, o evento será tratado pelo div Primeiro (clique em manipuladores de eventos no div irá disparar primeiro), depois no ul, depois no último no elemento alvo, li.

No modelo borbulhante, o oposto acontecerá: o evento será primeiro tratado pelo li, depois pelo ul, e finalmente pelo elemento div.

Para mais informações, ver

No exemplo abaixo, se você clicar em qualquer um dos elementos destacados, você pode ver que a fase de captura do fluxo de propagação do evento ocorre primeiro, seguido pela fase borbulhante.

var logElement = document.getElementById('log');

function log(msg) {
    logElement.innerHTML += ('<p>' + msg + '</p>');
}

function capture() {
    log('capture: ' + this.firstChild.nodeValue.trim());
}

function bubble() {
    log('bubble: ' + this.firstChild.nodeValue.trim());
}

var divs = document.getElementsByTagName('div');
for (var i = 0; i < divs.length; i++) {
    divs[i].addEventListener('click', capture, true);
    divs[i].addEventListener('click', bubble, false);
}
p {
    line-height: 0;
}

div {
    display:inline-block;
    padding: 5px;

    background: #fff;
    border: 1px solid #aaa;
    cursor: pointer;
}

div:hover {
    border: 1px solid #faa;
    background: #fdd;
}
<div>1
    <div>2
        <div>3
            <div>4
                <div>5</div>
            </div>
        </div>
    </div>
</div>
<section id="log"></section>

Outro exemplo em JSFiddle .

 1180
Author: Arun P Johny, 2017-07-12 16:07:33

Designação das mercadorias:

quirksmode.org tem uma boa descrição disto. Em poucas palavras (copiado de quirksmode):

Captura de Eventos

Quando usar a captura de Eventos

               | |
---------------| |-----------------
| element1     | |                |
|   -----------| |-----------     |
|   |element2  \ /          |     |
|   -------------------------     |
|        Event CAPTURING          |
-----------------------------------

O responsável pelo evento do element1 dispara primeiro, o responsável pelo evento do element2 dispara em último.

Borbulhar o evento

Quando se usa a borbulhagem de Eventos

               / \
---------------| |-----------------
| element1     | |                |
|   -----------| |-----------     |
|   |element2  | |          |     |
|   -------------------------     |
|        Event BUBBLING           |
-----------------------------------

O manipulador de eventos do element2 dispara. primeiro, o responsável pelo evento do element1 dispara Por último.


O que usar?

Depende do que queres fazer. Não há melhor. A diferença é a ordem de execução dos responsáveis pelo evento. Na maioria das vezes, não há problema em disparar os manipuladores de eventos na fase bubbling , mas também pode ser necessário despedi-los mais cedo.
 460
Author: Felix Kling, 2011-01-06 15:46:18

Se existirem dois elementos, elemento 1 e Elemento 2. O elemento 2 está dentro do elemento 1 e anexamos um manipulador de eventos com ambos os elementos, digamos onClick. Agora, quando clicarmos no elemento 2, então eventHandler para ambos os elementos será executado. Agora aqui a questão é em que ordem o evento será executado. Se o evento associado ao elemento 1 Executar primeiro é chamado captura de eventos e se o evento associado ao elemento 2 Executar primeiro isto é chamado de borbulhamento de eventos. De acordo com W3C o evento começará na fase de captura até atingir o alvo voltar ao elemento e então ele começa a borbulhar

Os estados de captura e borbulhagem são conhecidos pelo parâmetro de Utilização do método addEventListener

Objectivo de Evento.addEventListener (tipo, ouvinte, [, useCapture]);

Por padrão a useCapture é falsa. Significa que está na fase borbulhante.

var div1 = document.querySelector("#div1");
var div2 = document.querySelector("#div2");

div1.addEventListener("click", function (event) {
  alert("you clicked on div 1");
}, true);

div2.addEventListener("click", function (event) {
  alert("you clicked on div 2");
}, false);
#div1{
  background-color:red;
  padding: 24px;
}

#div2{
  background-color:green;
}
<div id="div1">
  div 1
  <div id="div2">
    div 2
  </div>
</div>
Por favor, tente com a mudar o verdadeiro e o falso.
 64
Author: dinesh_malhotra, 2017-06-25 22:16:47

Encontrei este tutorial em javascript.info para ser muito claro na explicação deste tópico. E seu resumo de 3 pontos no final está realmente falando com os pontos cruciais. Passo a citar:

    Os eventos primeiro são capturados até ao alvo mais profundo,depois sobem. Em Ou seja, Todos os manipuladores trabalham com excepção do estágio borbulhante. addEventListener com o último argumento verdadeiro, que é a única maneira de apanhe o evento ao capturar o palco.
  1. borbulhar / capturar pode ser parou por evento.cancelBubble=true (IE) ou event.stopPropagation () para outros navegadores.
 23
Author: gm2008, 2015-05-14 08:51:09
Há também o Event.eventPhase propriedade que pode dizer-lhe se o evento está no alvo ou vem de outro lugar.

Note que a compatibilidade do navegador ainda não foi determinada. Testei-o em cromo (66.0.3359.181) e Firefox (59.0.3) e é suportado lá.

Expandindo-se no já grande trecho da resposta aceite , Este é o resultado usando a propriedade eventPhase

var logElement = document.getElementById('log');

function log(msg) {
  if (logElement.innerHTML == "<p>No logs</p>")
    logElement.innerHTML = "";
  logElement.innerHTML += ('<p>' + msg + '</p>');
}

function humanizeEvent(eventPhase){
  switch(eventPhase){
    case 1: //Event.CAPTURING_PHASE
      return "Event is being propagated through the target's ancestor objects";
    case 2: //Event.AT_TARGET
      return "The event has arrived at the event's target";
    case 3: //Event.BUBBLING_PHASE
      return "The event is propagating back up through the target's ancestors in reverse order";
  }
}
function capture(e) {
  log('capture: ' + this.firstChild.nodeValue.trim() + "; " + 
  humanizeEvent(e.eventPhase));
}

function bubble(e) {
  log('bubble: ' + this.firstChild.nodeValue.trim() + "; " + 
  humanizeEvent(e.eventPhase));
}

var divs = document.getElementsByTagName('div');
for (var i = 0; i < divs.length; i++) {
  divs[i].addEventListener('click', capture, true);
  divs[i].addEventListener('click', bubble, false);
}
p {
  line-height: 0;
}

div {
  display:inline-block;
  padding: 5px;

  background: #fff;
  border: 1px solid #aaa;
  cursor: pointer;
}

div:hover {
  border: 1px solid #faa;
  background: #fdd;
}
<div>1
  <div>2
    <div>3
      <div>4
        <div>5</div>
      </div>
    </div>
  </div>
</div>
<button onclick="document.getElementById('log').innerHTML = '<p>No logs</p>';">Clear logs</button>
<section id="log"></section>
 1
Author: Adelin, 2018-05-29 12:54:00