Pregunta ¿Qué es el evento burbujeando y capturando?


¿Cuál es la diferencia entre el burbujeo del evento y la captura? De los dos, ¿cuál es el modelo más rápido y mejor para usar?


826
2018-01-06 15:44


origen


Respuestas:


El borrado y la captura de eventos son dos formas de propagación de eventos en la API HTML DOM, cuando un evento ocurre en un elemento dentro de otro elemento, y ambos elementos han registrado un identificador para ese evento. El modo de propagación de eventos determina en que orden los elementos reciben el evento.

Con burbujeo, el evento es capturado y manejado por el elemento más interno y luego propagado a elementos externos.

Con la captura, el evento es capturado primero por el elemento más externo y se propaga a los elementos internos.

La captura también se denomina "goteo", que ayuda a recordar el orden de propagación:

gotear, burbujear

En los viejos tiempos, Netscape abogó por la captura de eventos, mientras que Microsoft promovió el burbujeo de eventos. Ambos son parte del W3C Eventos de modelo de objetos de documento estándar (2000).

IE <9 usos solo evento burbujeando, mientras que IE9 + y todos los principales navegadores soportan ambos. Por otro lado, el el rendimiento del burbujeo del evento puede ser ligeramente inferior para DOM complejos.

Podemos usar el addEventListener(type, listener, useCapture) para registrar los manejadores de eventos en el modo de burbujeo (predeterminado) o de captura. Para usar el modelo de captura, pase el tercer argumento como true.

Ejemplo

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

En la estructura anterior, suponga que se produjo un evento de clic en el li elemento.

En el modelo de captura, el evento será manejado por div primero (haga clic en los controladores de eventos en div disparará primero), luego en el ul, luego en el último en el elemento objetivo, li.

En el modelo burbujeante, ocurrirá lo contrario: el evento será manejado primero por el li, luego por el ul, y finalmente por el div elemento.

Para más información, ver

En el ejemplo siguiente, si hace clic en cualquiera de los elementos resaltados, puede ver que la fase de captura del flujo de propagación del evento se produce primero, seguido de la fase de burbujeo.

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>

Otro ejemplo en JSFiddle.


1146
2018-01-06 15:47



Descripción:

quirksmode.org tiene una buena descripción de esto. En pocas palabras (copiado de quirksmode):

Captura de eventos

Cuando usa captura de eventos

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

el controlador de eventos del elemento1 dispara primero, el controlador de eventos del elemento2 dispara al último.

Evento burbujeante

Cuando usa evento de burbujeo

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

el controlador de eventos de element2 dispara primero, el controlador de eventos de element1 se dispara al último.


Qué usar?

Depende de lo que quieras hacer. No hay mejor La diferencia es el orden de la ejecución de los controladores de eventos. La mayoría de las veces estará bien disparar controladores de eventos en el burbujeo pero también puede ser necesario dispararlos antes.


455
2018-01-06 15:46



Si hay dos elementos, el elemento 1 y el elemento 2. El elemento 2 está dentro del elemento 1 y adjuntamos un controlador de eventos con ambos elementos, digamos onClick. Ahora cuando hacemos clic en el elemento 2, se ejecutará eventHandler para ambos elementos. Ahora aquí la pregunta es en qué orden se ejecutará el evento. Si el evento adjunto con el elemento 1 se ejecuta primero, se llama captura de eventos y si el evento adjunto con el elemento 2 se ejecuta primero, esto se conoce como evento de burbujeo. De acuerdo con W3C, el evento comenzará en la fase de captura hasta que llegue al objetivo vuelva al elemento y luego comience a burbujear

Los estados de captura y burbujeo son conocidos por el parámetro useCapture del método addEventListener

eventTarget.addEventListener (type, listener, [, useCapture]);

Por defecto useCapture es falso. Significa que está en la fase de burbujeo.

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, intente con cambiar verdadero y falso.


63
2018-03-04 12:45



He encontrado esto tutorial en javascript.info ser muy claro al explicar este tema. Y su resumen de 3 puntos al final realmente está hablando de los puntos cruciales. Lo cito aquí:

  1. Los eventos primero se capturan hasta el objetivo más profundo, luego se inflaman. En   IE <9 solo burbujean.
  2. Todos los controladores trabajan en etapas de burbujeo exceptts   addEventListener con el último argumento verdadero, que es la única forma de   atrapa el evento en la etapa de captura.
  3. Burbujeo / captura puede ser   detenido por event.cancelBubble = true (IE) o event.stopPropagation ()   para otros navegadores.

23
2018-05-14 08:51



También está el Event.eventPhase propiedad que le puede decir si el evento está en el objetivo o proviene de otro lugar.

Tenga en cuenta que la compatibilidad del navegador aún no está determinada. Lo probé en Chrome (66.0.3359.181) y Firefox (59.0.3) y es compatible allí.

Expandiendo en el ya gran fragmento de la respuesta aceptada, este es el resultado usando el eventPhase propiedad

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>


0
2018-05-29 07:31