• Sobre mí
  • Proyectos
  • Contacto
  • Blog

Apasionado por el desarrollo web y el diseño de interfaces intuitivas.

Cada error es un paso. Cada línea, un aprendizaje.

📍   Salou, Tarragona, España ✉️   [email protected] 📞   +34 641932611

Curriculum

Ver mi curriculum completo

Mapa del sitio

  • Inicio
  • Blog
  • Proyectos
  • Sobre mi
  • Mi misión
  • Sitemap

Contácto

  • Página de contácto
  • LinkedIn
  • GitHub

2026 Frankuxui - Todos los derechos reservados

  • Términos y condiciones
  • Política de privacidad
  • Política de cookies
Imagen de unsplash creada por Benjamin Chambon
Imagen de unsplash creada por Benjamin Chambon
  • JavaScript

Articulo publicado el 13 de julio de 2026

Por Frank Esteban Isdray Junco

Event Delegation: Optimiza tus listeners en JavaScript

Maneja eventos en múltiples elementos con un único listener y mejora el rendimiento de tu aplicación

Qué es Event Delegation

Event delegation es una técnica en JavaScript que aprovecha el event bubbling (propagación de eventos) para manejar eventos en múltiples elementos usando un único listener. En lugar de añadir un listener a cada elemento individual, lo añades a un contenedor padre y esperas a que los eventos "burbujeen" hacia arriba.

Esta técnica es especialmente útil cuando trabajas con elementos dinámicos, listas largas o aplicaciones que crean elementos en tiempo de ejecución. Sin event delegation, tendrías que añadir listeners cada vez que creas un nuevo elemento, lo cual es ineficiente y propenso a errores.

El problema sin Event Delegation

Imagina que tienes una lista de tareas donde el usuario puede eliminar elementos:

html
<ul id="taskList">
  <li><span class="task-name">Comprar leche</span> <button class="delete-btn">Eliminar</button></li>
  <li><span class="task-name">Pagar facturas</span> <button class="delete-btn">Eliminar</button></li>
  <li><span class="task-name">Estudiar JavaScript</span> <button class="delete-btn">Eliminar</button></li>
</ul>

Sin event delegation, necesitarías algo así:

javascript
const deleteButtons = document.querySelectorAll(".delete-btn");
deleteButtons.forEach((button) => {
  button.addEventListener("click", function () {
    this.parentElement.remove();
  });
});

El problema es que si añades nuevas tareas dinámicamente, los nuevos botones no tendrán el listener:

javascript
// Este botón NO tendrá el listener de eliminación
const newTask = document.createElement("li");
newTask.innerHTML = '<span class="task-name">Nueva tarea</span> <button class="delete-btn">Eliminar</button>';
document.getElementById("taskList").appendChild(newTask);

Cómo implementar Event Delegation

Con event delegation, añades un único listener al elemento padre y usas event.target para identificar en qué elemento se hizo clic:

javascript
const taskList = document.getElementById("taskList");

taskList.addEventListener("click", function (event) {
  // Verificar si el elemento clickeado es un botón de eliminar
  if (event.target.classList.contains("delete-btn")) {
    // Eliminar la tarea (elemento padre del botón)
    event.target.parentElement.remove();
  }
});

Ahora, cuando añadas nuevas tareas, los botones funcionarán automáticamente sin necesidad de añadir listeners adicionales:

javascript
const newTask = document.createElement("li");
newTask.innerHTML = '<span class="task-name">Nueva tarea</span> <button class="delete-btn">Eliminar</button>';
document.getElementById("taskList").appendChild(newTask); // ¡Funciona sin configuración adicional!

Ventajas de la Event Delegation

Mayor rendimiento

Usar un único listener es mucho más eficiente que tener múltiples listeners. Menos listeners significa menos consumo de memoria y mejor rendimiento, especialmente en listas con cientos o miles de elementos.

Memoria y velocidad

El impacto en memoria es exponencial con el número de elementos. Un listener ocupa aproximadamente 100-200 bytes en memoria, por lo que con 1000 elementos adicionales, estarías gastando 100-200KB innecesarios.

javascript
// Mal: 1000 listeners
const items = document.querySelectorAll(".item");
items.forEach((item) => {
  item.addEventListener("click", handler);
});

// Bien: 1 listener
const container = document.getElementById("container");
container.addEventListener("click", function (event) {
  if (event.target.classList.contains("item")) {
    handler(event);
  }
});

Soporte automático para elementos dinámicos

Una de las mayores ventajas es que no necesitas actualizar los listeners cuando creas nuevos elementos. El listener en el contenedor padre capturará los eventos de cualquier elemento hijo, aunque se cree después de que el listener se haya instalado.

Código más limpio y mantenible

Con event delegation, el código es más conciso y fácil de mantener. No tienes que preocuparte por limpiar listeners o attachear nuevos listeners a nuevos elementos.

Cuándo usar Event Delegation

✅ Cuándo SÍ usar

  • Listas dinámicas: Cuando añades o removes elementos regularmente
  • Elementos creados en tiempo de ejecución: Con AJAX, fetch, o JavaScript vanilla
  • Muchos elementos similares: Botones, enlaces, items en listas largas
  • Optimización de rendimiento: Cuando tienes cientos o miles de elementos interactivos

❌ Cuándo NO usar

  • Eventos que no burbujean: Como focus, blur, load, unload (estos no se propagan hacia arriba)
  • Necesidad de especificidad extrema: Si solo un elemento específico necesita el listener
  • Eventos de teclado complejos: Cuando necesitas listeners muy específicos en elementos individuales

Ejemplo práctico completo

Aquí hay un ejemplo de una aplicación de tareas usando event delegation:

javascript
class TaskApp {
  constructor(listSelector) {
    this.list = document.querySelector(listSelector);
    this.init();
  }

  init() {
    // Un único listener para toda la lista
    this.list.addEventListener("click", (event) => this.handleClick(event));
  }

  handleClick(event) {
    const deleteBtn = event.target.closest(".delete-btn");
    const editBtn = event.target.closest(".edit-btn");

    if (deleteBtn) {
      this.deleteTask(deleteBtn);
    } else if (editBtn) {
      this.editTask(editBtn);
    }
  }

  deleteTask(button) {
    button.closest("li").remove();
  }

  editTask(button) {
    const taskName = button.closest("li").querySelector(".task-name");
    const newName = prompt("Nuevo nombre:", taskName.textContent);
    if (newName) {
      taskName.textContent = newName;
    }
  }
}

// Usar la aplicación
const app = new TaskApp("#taskList");

Usando closest() para capas

El método closest() es tu amigo en event delegation. Te permite encontrar el ancestro más cercano que coincida con un selector, lo cual es más robusto que verificar event.target directamente:

javascript
// Frágil: Asume que el botón es el elemento clickeado
if (event.target.classList.contains("delete-btn")) {
}

// Robusto: Funciona incluso si haces clic en un icono dentro del botón
const button = event.target.closest(".delete-btn");
if (button) {
}

Casos de uso en aplicaciones reales

Aplicaciones de todo-list

Las aplicaciones de tareas son un caso perfecto para event delegation. Tienes una lista que crece dinámicamente y múltiples acciones por item (eliminar, editar, completar, etc.).

Tablas dinámicas

Cuando renderizas tablas desde API responses, la event delegation evita que tengas que attachear listeners a cada fila:

javascript
const tbody = document.querySelector("table tbody");
tbody.addEventListener("click", function (event) {
  const row = event.target.closest("tr");
  if (!row) return;

  const editBtn = event.target.closest(".edit-btn");
  const deleteBtn = event.target.closest(".delete-btn");

  if (editBtn) editRow(row);
  if (deleteBtn) deleteRow(row);
});

Componentes reutilizables

Cuando construyes componentes reutilizables que se instancian múltiples veces en la página, event delegation simplifica significativamente la gestión de eventos.

Rendimiento: números reales

Comparemos el rendimiento entre sin event delegation y con event delegation:

javascript
// Scenario: 1000 elementos con listeners individuales
console.time("Sin Event Delegation");
const elements = document.querySelectorAll(".item");
elements.forEach((el) => {
  el.addEventListener("click", () => {});
});
console.timeEnd("Sin Event Delegation"); // ~15-25ms

console.time("Con Event Delegation");
const container = document.getElementById("container");
container.addEventListener("click", (e) => {
  if (e.target.classList.contains("item")) {
  }
});
console.timeEnd("Con Event Delegation"); // ~1-2ms

En aplicaciones con miles de elementos, la diferencia de rendimiento es muy notable, especialmente en dispositivos móviles o con menos recursos.

Resumen

¿Cuál es la mejor práctica?

La respuesta es usar event delegation por defecto en listas dinámicas y contenedores con múltiples elementos interactivos. Solo evítala si tienes eventos especiales que no burbujean o necesitas listeners muy específicos.

La event delegation es una técnica fundamental en JavaScript que te permite:

  • Optimizar el rendimiento usando un único listener en lugar de múltiples
  • Simplificar la gestión de eventos en listas dinámicas
  • Escribir código más limpio y mantenible
  • Evitar memory leaks causados por listeners no removidos

Recuerda usar event.target.closest() para una captura robusta de elementos y aplica esta técnica siempre que trabajes con listas dinámicas o elementos creados en tiempo de ejecución.

En este artículo

  1. Qué es Event Delegation
  2. El problema sin Event Delegation
  3. Cómo implementar Event Delegation
  4. Ventajas de la Event Delegation
  5. Mayor rendimiento
  6. Memoria y velocidad
  7. Soporte automático para elementos dinámicos
  8. Código más limpio y mantenible
  9. Cuándo usar Event Delegation
  10. ✅ Cuándo SÍ usar
  11. ❌ Cuándo NO usar
  12. Ejemplo práctico completo
  13. Usando closest() para capas
  14. Casos de uso en aplicaciones reales
  15. Aplicaciones de todo-list
  16. Tablas dinámicas
  17. Componentes reutilizables
  18. Rendimiento: números reales
  19. Resumen

Articulos relacionados

Estos articulos pueden interesarte si te gusto este articulo.

Imagen de unsplash creada por Peter Burdon
Imagen del articulo Fotografía de Unsplash
13 de julio de 2026
JavaScript

Debounce y Throttle: Controla la frecuencia de ejecución de funciones

Optimiza el rendimiento de tu aplicación limitando cuántas veces se ejecutan listeners de eventos y funciones costosas

Imagen de unsplash creada por Frans Ruiter
Imagen del articulo Fotografía de Unsplash
13 de julio de 2026
JavaScript

Event Delegation en JavaScript Vanilla: Optimiza tu DOM

Cómo reducir listeners y mejorar el rendimiento usando bubbling de eventos

Fotografía de unsplash creada por Carter Obasohan
Imagen del articulo Los atributos data-* permiten enlazar datos y comportamiento en HTML
8 de julio de 2026
HTML
·JavaScript

Atributos data-* en HTML: Almacena datos personalizados en tu DOM

Aprende a usar los atributos data-* para guardar información en elementos HTML y accederla desde JavaScript de forma segura y semántica