¿Qué es el burbujeo de eventos y la captura de eventos en JavaScript?

El burbujeo de eventos y la captura de eventos son los dos conceptos interesantes de JavaScript. Antes de profundizar en estos conceptos fascinantes, primero sepamos qué es un oyente de eventos . Un detector de eventos es básicamente una función que espera a que ocurra un evento. Ese evento puede ser cualquier cosa como un evento de clic del mouse, enviar un formulario, presionar las teclas de un teclado, etc.

Un detector de eventos contiene tres parámetros y se puede definir mediante la siguiente sintaxis.

<element>.addEventListener(<eventName>, 
    <callbackFunction>, {capture : boolean});
  • <elemento>: el elemento al que se adjunta un detector de eventos.
  • <nombre del evento>: puede ser eventos de ‘clic’, ‘tecla arriba’, ‘tecla abajo’, etc.
  • <callbackFunction>: esta función se activa después de que ocurrió el evento.
  • {capture: boolean}: Indica si el evento estará en fase de captura o en fase de burbujeo (opcional)

Ejemplo 1: tomemos un ejemplo para comprender el burbujeo de eventos y la captura de eventos.

HTML

<!DOCTYPE html>
<html>
 
<head>
    <script src=
"https://code.jquery.com/jquery-3.6.0.min.js">
    </script>
    <style>
        div {
            color: white;
            display: flex;
            justify-content: center;
            align-items: center;
            flex-direction: column;
        }
        h2 {
            color: black;
        }
        #grandparent {
            background-color: green;
            width: 300px;
            height: 300px;
        }
        #parent {
            background-color: blue;
            width: 200px;
            height: 200px;
        }
        #child {
            background-color: red;
            width: 100px;
            height: 100px;
        }
    </style>
</head>
 
<body>
    <div>
        <h2>Welcome To GFG</h2>
        <div id="grandparent">GrandParent
            <div id="parent">Parent
                <div id="child">Child</div>
            </div>
        </div>
    </div>
 
    <script>
        const grandParent = document.getElementById("grandparent");
        const parent = document.getElementById("parent");
        const child = document.getElementById("child");
 
        grandParent.addEventListener("click", (e) => {
            console.log("GrandParent");
        }, { capture: false });
        parent.addEventListener("click", (e) => {
            console.log("Parent");
        }, { capture: false });
        child.addEventListener("click", (e) => {
            console.log("Child");
        }, { capture: false });
    </script>
</body>
</html>

Producción:

Cuando hicimos clic en el div con el niño como su id, deberíamos obtener la salida como ‘niño’ en nuestra consola. Pero inesperadamente, recibimos un resultado diferente incluso si no hemos hecho clic en divs con padre y abuelo como su identificación. El concepto de burbujeo de eventos entra en escena. El div hijo se encuentra dentro del div padre así como en el div abuelo. Entonces, cuando el div secundario hizo clic, indirectamente hicimos clic tanto en el div principal como en el div abuelo. Por lo tanto, la propagación se mueve desde el interior hacia el exterior en el DOM o podemos decir que los eventos se están hinchando. 

Por lo tanto, el proceso de propagación desde el elemento más cercano al elemento más lejano en el DOM (Document Object Modal) se denomina burbujeo de eventos.

Ejemplo 2: en el ejemplo anterior, cambiemos el valor del tercer parámetro de addEventListener() y veamos qué cambios se realizarán en la salida.

HTML

<!DOCTYPE html>
<html>
<head>
    
    <style>
        div {
            color: white;
            display: flex;
            justify-content: center;
            align-items: center;
            flex-direction: column;
        }
        h2 {
            color: black;
        }
        #grandparent {
            background-color: green;
            width: 300px;
            height: 300px;
        }
        #parent {
            background-color: blue;
            width: 200px;
            height: 200px;
        }
        #child {
            background-color: red;
            width: 100px;
            height: 100px;
        }
    </style>
</head>
 
<body>
    <div>
        <h2>Welcome To GFG</h2>
        <div id="grandparent">GrandParent
            <div id="parent">Parent
                <div id="child"> Child</div>
            </div>
        </div>
    </div>
    <script>
        const grandParent = document.getElementById("grandparent");
        const parent = document.getElementById("parent");
        const child = document.getElementById("child");
         
        // Changing value of capture parameter as 'true'
        grandParent.addEventListener("click", (e) => {
            console.log("GrandParent");
        }, { capture: true });
        parent.addEventListener("click", (e) => {
            console.log("Parent");
        }, { capture: true });
        child.addEventListener("click", (e) => {
            console.log("Child");
        }, { capture: true });
    </script>
</body>
 
</html>

Es claramente visible que los divs antecesores del div secundario se imprimían primero y luego el propio div secundario . Entonces, el proceso de propagación desde el elemento más lejano al elemento más cercano en el DOM se llama captura de eventos . Ambos términos son justo opuestos entre sí.

Ejemplo 3: Juguemos un poco más con el código para una mejor comprensión.

HTML

<!DOCTYPE html>
<html>
 
<head>  
    <style>
        div {
            color: white;
            display: flex;
            justify-content: center;
            align-items: center;
            flex-direction: column;
        }
        h2 {
            color: black;
        }
        #grandparent {
            background-color: green;
            width: 300px;
            height: 300px;
        }
        #parent {
            background-color: blue;
            width: 200px;
            height: 200px;
        }
        #child {
            background-color: red;
            width: 100px;
            height: 100px;
        }
    </style>
</head>
 
<body>
    <div>
        <h2>Welcome To GFG</h2>
        <div id="grandparent">GrandParent
            <div id="parent">Parent
                <div id="child"> Child</div>
            </div>
        </div>
    </div>
 
    <script>
        const grandParent = document.getElementById("grandparent");
        const parent = document.getElementById("parent");
        const child = document.getElementById("child");
         
        document.addEventListener("click", (e) => {
            console.log("Document capturing");
        }, { capture: true });
         
        grandParent.addEventListener("click", (e) => {
            console.log("GrandParent capturing");
        }, { capture: true });
         
        parent.addEventListener("click", (e) => {
            console.log("Parent capturing");
        }, { capture: true });
         
        child.addEventListener("click", (e) => {
            console.log("Child capturing");
        }, { capture: true });
          document.addEventListener("click", (e) => {
            console.log("Document bubbling");
        }, { capture: false });
         
        grandParent.addEventListener("click", (e) => {
            console.log("GrandParent bubbling");
        }, { capture: false });
         
        parent.addEventListener("click", (e) => {
            console.log("Parent bubbling");
        }, { capture: false });
         
        child.addEventListener("click", (e) => {
            console.log("Child bubbling");
        }, { capture: false });
    </script>
</body>
 
</html>

Salida: si hicimos clic en el div con id child, esta será la salida.

Podemos ver que la captura de eventos de los oyentes de eventos ocurrió primero y luego ocurrió el burbujeo de eventos. Esto significa que la propagación de los detectores de eventos primero va de afuera hacia adentro y luego de adentro hacia afuera en el DOM. 

¿Cómo detener el burbujeo y la captura de eventos?

En el ejemplo anterior, podemos ver un parámetro «e» (o a veces llamado «evento») en la función de devolución de llamada de addEventListener() . Es un objeto de evento que define automáticamente cuando agregamos un detector de eventos a un elemento. Este objeto ‘e’ tiene una función llamada stopPropagation() que ayuda a prevenir este molesto comportamiento.

Ejemplo 4: Veamos qué sucederá cuando hagamos clic en child div en el siguiente código.

HTML

<!DOCTYPE html>
<html>
 
<head>
    <style>
        div {
            color: white;
            display: flex;
            justify-content: center;
            align-items: center;
            flex-direction: column;
        }
        h2 {
            color: black;
        }
        #grandparent {
            background-color: green;
            width: 300px;
            height: 300px;
        }
        #parent {
            background-color: blue;
            width: 200px;
            height: 200px;
        }
        #child {
            background-color: red;
            width: 100px;
            height: 100px;
        }
    </style>
</head>
 
<body>
    <div>
        <h2>Welcome To GFG</h2>
        <div id="grandparent">GrandParent
            <div id="parent">Parent
                <div id="child"> Child</div>
            </div>
        </div>
    </div>
 
    <script>
        const grandParent = document.getElementById("grandparent");
        const parent = document.getElementById("parent");
        const child = document.getElementById("child");
        grandParent.addEventListener("click", (e) => {
            console.log("GrandParent bubbling");
        });
        parent.addEventListener("click", (e) => {
            e.stopPropagation();  //syntax to stop event bubbling
            console.log("Parent bubbling");
        });
        child.addEventListener("click", (e) => {
            console.log("Child bubbling");
        });
    </script>
</body>
 
</html>

Producción:

Si hicimos clic en child div , la propagación se detiene en parent div y no se mueve a grandparent div . Por lo tanto, se evita el burbujeo de eventos. 

Nota: La captura de eventos también se puede evitar de la misma manera.

Puntos importantes a recordar:

  • Si no mencionamos ningún tercer parámetro en addEventListener() , entonces, de forma predeterminada, se producirá un burbujeo de eventos.
  • El burbujeo de eventos y la captura de eventos ocurren solo cuando el elemento y todos sus ancestros tienen el mismo detector de eventos (en nuestro caso, el evento ‘clic’) adjunto a ellos.

Conclusión: hemos aprendido sobre el burbujeo y la captura de eventos y estos son algunos puntos clave.

  • La captura de eventos significa que la propagación del evento se realiza desde los elementos ancestros al elemento secundario en el DOM, mientras que el burbujeo de eventos significa que la propagación se realiza desde el elemento secundario a los elementos ancestros en el DOM.
  • La captura de eventos ocurre seguida por el burbujeo de eventos.
  • Si {capture: true}, se producirá la captura de eventos; de lo contrario, se producirá un burbujeo de eventos.
  • Ambos pueden evitarse utilizando el método stopPropagation() .

Publicación traducida automáticamente

Artículo escrito por iaditijain08 y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *