Cargando...

Delegación de eventos

En la ventanilla hay una tira. El padre es #strip. Ya lleva dos botones: #red, con el texto red, y #blue, con el texto blue. Debajo, #note dice blank.
No hace falta un oyente en cada botón. Una llamada a addEventListener en la tira basta. El clic de un botón de dentro sube hasta la tira. event.target es el botón. event.currentTarget es la tira, el elemento donde está este oyente.
El botón #gold todavía no está en la página. Se crea después de guardar el oyente, se añade a la tira y se pulsa. La misma función corre. La nota pasa a gold. El script pulsa red, luego blue, luego gold. addEventListener se llamó una vez, así que hands vale 1. La línea bajo la tira es red / blue / gold / 1. Estos botones son type="button". Aquí no se llama a preventDefault ni a stopPropagation. Eso era la página de la placa, y allí no se añadía un hijo después del oyente.

Un oyente para cada billete

La página de la placa nombraba event y leía type, target y currentTarget en un enlace dentro del muro. Su línea era click / seal / plaque / true / quiet. El perchero guardaba wool y silk sin parámetro. Su línea era wool silk / 2 / peg. Aquí el parámetro event se queda, pero target hace otro trabajo: decir qué hijo recibió el clic, aunque ese hijo aún no existiera.
getElementById solo te da la tira, el botón rojo, el botón azul y la nota. Gold nace de createElement. Un oyente en red y otro en blue no oyen gold, salvo que vuelvas a engancharlo después de appendChild. Un oyente en la tira no necesita ese segundo enganche. Lee currentTarget dentro de la función. Cuando la función vuelve, esa propiedad es null.

Qué anota la tira

La nota empieza en blank. Los rótulos siguen siendo red y blue; gold llega después. Lee las filas en orden. Cada fragmento parte de la tira con dos botones, menos la fila de la página, que es la demo de abajo. Esa demo llama a addEventListener una vez.

📊 Qué anota la tira

Momento Qué lees Texto de la nota Confusión fácil
oyente en la tira, clic en red event.target.id red leer currentTarget, que es strip
el mismo clic, leer currentTarget event.currentTarget.id strip leer el id del billete
el mismo oyente, clic en blue event.target.id blue dar a blue su propio oyente
gold creado después del oyente y pulsado event.target.id gold creer que el botón nuevo calla
clic en la tira, con el guarda la nota skip escribir el id strip
script de la página la línea red / blue / gold / 1 la línea de la placa, o un 3 final

Un clic en un botón es un solo evento. target sigue siendo ese botón para cada oyente del camino. Aquí hay un oyente, en la tira, así que mientras corre la función currentTarget es la tira. El clic llega porque nadie llama a stopPropagation. La página de la placa cortaba ese viaje. Esta no.
preventDefault sirve para una acción por defecto del navegador, como un enlace que se va de la página. Estos controles son botones, no enlaces. No llamar a preventDefault es la página entera, no una línea que falta.
Si event.target y event.currentTarget son el mismo nodo, el clic cayó en la tira, no en un botón. La función escribe skip y no trata el papel como billete. seen.join(" / ") solo une ids que ya entraron en seen. hands va después. El último token es cuántas veces se llamó a addEventListener, no cuántos billetes se pulsaron.

El billete bajo el clic

El oyente está en la tira. La función nombra el parámetro event y escribe event.target.id en la nota. Luego la página pulsa red. No llama a addEventListener sobre red.

Leer el billete

javascript
let strip = document.getElementById("strip");
let note = document.getElementById("note");
function take(event) {
note.textContent = event.target.id;
}
strip.addEventListener("click", take);
document.getElementById("red").click();
console.log(note.textContent);

La salida es red. El elemento del oyente es la tira. target no informa del padre. Informa del botón que quedó bajo el clic.

Quién tiene el oyente

Tira nueva, el mismo oyente, el mismo clic en red. La nota escribe los dos ids: primero target, luego currentTarget.

Leer los dos ids

javascript
let strip = document.getElementById("strip");
let note = document.getElementById("note");
function take(event) {
note.textContent = event.target.id + " " + event.currentTarget.id;
}
strip.addEventListener("click", take);
document.getElementById("red").click();
console.log(note.textContent);

La salida es red strip. La primera palabra es el billete. La segunda es el elemento dueño de este oyente. Si el oyente estuviera en el propio red y pulsaras red, saldría red red. Esta lectura usa la tira, por eso los ids difieren.

El billete que ya estaba al lado

Otra tira nueva. Un oyente, todavía solo en la tira. Esta vez el clic es blue. Blue estaba en el marcado desde el principio. No tiene oyente propio.

Oír el otro billete

javascript
let strip = document.getElementById("strip");
let note = document.getElementById("note");
function take(event) {
note.textContent = event.target.id;
}
strip.addEventListener("click", take);
document.getElementById("blue").click();
console.log(note.textContent);

La salida es blue. Un solo addEventListener cubrió los dos botones que ya estaban dentro de la tira. Blue no sustituyó a red. Red no necesitó una segunda llamada.

Un billete impreso más tarde

Primero se guarda el oyente. Después la página crea un botón, pone su id en gold, type en button, el texto en gold y lo añade a la tira. Solo entonces pulsa gold.

Oír un billete tardío

javascript
let strip = document.getElementById("strip");
let note = document.getElementById("note");
function take(event) {
note.textContent = event.target.id;
}
strip.addEventListener("click", take);
let gold = document.createElement("button");
gold.id = "gold";
gold.type = "button";
gold.textContent = "gold";
strip.appendChild(gold);
gold.click();
console.log(note.textContent);

La salida es gold. Gold no existía cuando corrió addEventListener. El clic sube de gold a la tira, y target es gold. No enganchas un oyente a gold.

Un clic en el papel

La tira también es un nodo que se puede pulsar. Si el target del clic es la tira, no hay id de billete que guardar. La función compara target con currentTarget. Si coinciden, la nota pasa a skip.

Ignorar el clic en la tira

javascript
let strip = document.getElementById("strip");
let note = document.getElementById("note");
function take(event) {
if (event.target === event.currentTarget) {
note.textContent = "skip";
return;
}
note.textContent = event.target.id;
}
strip.addEventListener("click", take);
strip.click();
console.log(note.textContent);

La salida es skip. Tanto target como currentTarget son la tira, así que el guarda rechaza el papel. Un clic en red sigue escribiendo red, porque esas dos referencias difieren. Sin el guarda, strip.click() escribiría el id strip en la nota.

La línea bajo la tira

El script va al final de body, cuando ya existen la tira y los párrafos. Se guarda un oyente y hands pasa a 1. Se pulsa red y luego blue. Cada id de billete entra en seen. Se crea gold, se añade y se pulsa, así que gold también entra en seen. La línea se escribe después de ese tercer clic. La página no pulsa la tira, por eso skip no está en la línea.

Demo de la página — tira de billetes

html
<!DOCTYPE html>
<html>
<head>
<title>event-delegation — page</title>
</head>
<body>
<div id="strip">
<button id="red" type="button">red</button>
<button id="blue" type="button">blue</button>
</div>
<p id="note">blank</p>
<p id="line">…</p>
<script>
let strip = document.getElementById("strip");
let note = document.getElementById("note");
let seen = [];
let hands = 0;
function take(event) {
if (event.target === event.currentTarget) {
note.textContent = "skip";
return;
}
note.textContent = event.target.id;
seen.push(event.target.id);
}
strip.addEventListener("click", take);
hands = hands + 1;
document.getElementById("red").click();
document.getElementById("blue").click();
let gold = document.createElement("button");
gold.id = "gold";
gold.type = "button";
gold.textContent = "gold";
strip.appendChild(gold);
gold.click();
document.getElementById("line").textContent =
seen.join(" / ") + " / " + hands;
</script>
</body>
</html>

La línea es red / blue / gold / 1. Los tres ids son los billetes pulsados, en ese orden. El último token es hands. addEventListener corrió una vez, así que el token es 1, no 3. La nota termina en gold porque gold fue el último clic. La palabra blank ya no está. La palabra skip no aparece. La línea de la placa y la del perchero son otras páginas.
Un botón que solo tiene texto deja event.target en el botón, así que id es red, blue o gold. Un span dentro del botón puede recibir el clic. El span no tiene id. Esta página no hace eso.

En la ventanilla

  1. Pon un oyente en la tira y pulsa red. La nota es red. Red no tiene oyente propio.
  2. Con ese mismo oyente, pulsa blue. La nota es blue.
  3. Crea gold, añádelo y púlsalo. La nota es gold. El oyente ya estaba en la tira.
  4. Pulsa la tira. Con el guarda, la nota es skip. Luego lee la línea: red / blue / gold / 1.

Tropiezos en la ventanilla

Los rótulos siguen diciendo red, blue y gold. La nota no es la palabra billete.

  • Un oyente en red y otro en blue, y luego la sorpresa de que gold calla
  • Leer event.currentTarget cuando querías el billete
  • Leer event.target cuando querías la tira
  • Olvidar el guarda, de modo que strip.click() escribe strip
  • Un span dentro del botón, así que target es el span y el id queda vacío
  • Llamar otra vez a addEventListener en gold y contar hands como 2
  • Llamar a preventDefault o a stopPropagation; eso era la placa
  • Esperar que el argumento de la función sea el elemento botón
  • Leer la línea como click / seal / plaque / true / quiet, o como wool silk / 2 / peg
  • Leer el último token como 3 porque se pulsaron tres billetes

Qué te queda

  • Un addEventListener en la tira oye cada botón de dentro
  • Al pulsar red, event.target.id es red y event.currentTarget.id es strip
  • El mismo oyente escribe blue cuando se pulsa blue
  • Gold, creado después del oyente, también escribe gold
  • Un clic en la tira, con el guarda, escribe skip
  • La línea de la página es red / blue / gold / 1

🧠 Pon a Prueba tu Conocimiento

Listo para Empezar

Pon a Prueba tu Conocimiento

Ponte a prueba con este cuestionario interactivo y descubre qué tan bien entiendes el tema

❓
8
Preguntas
🎯
70%
Para Aprobar
♾️
∞
Tiempo
🔄
∞
Intentos

📝 Instrucciones

  • Lee cada pregunta cuidadosamente
  • Selecciona la mejor respuesta para cada pregunta
  • Puedes repetir el quiz tantas veces como quieras
  • Tu progreso se mostrará en la parte superior