CodeGym /Cursos /Frontend SELF ES /Optimización de eventos

Optimización de eventos

Frontend SELF ES
Nivel 42 , Lección 3
Disponible

9.1 Delegación de eventos

Trabajar con eventos en JavaScript puede requerir una gestión compleja para optimizar el rendimiento y mejorar la arquitectura de la aplicación.

La optimización del manejo de eventos en JavaScript es crucial para crear aplicaciones web eficientes, especialmente cuando se trabaja con un gran número de elementos. En este contexto, la delegación de eventos y la prevención de manejadores innecesarios juegan un papel clave.

La delegación de eventos es un patrón en el que el manejador de eventos se establece en el elemento padre, en lugar de en cada elemento hijo individual. Esto permite gestionar eficazmente los eventos de un gran número de elementos hijos, ya que el manejador se invoca solo una vez para el padre, en lugar de para cada elemento.

Ejemplo sin delegación de eventos:

HTML
    
      <!DOCTYPE html>
      <html>
        <head>
          <title>Ejemplo de delegación de eventos</title>
        </head>
        <body>
          <ul id="list">
            <li>Elemento 1</li>
            <li>Elemento 2</li>
            <li>Elemento 3</li>
          </ul>
          <script>
            const list = document.querySelector('ul');
            const items = document.querySelectorAll('#list li');

            items.forEach(item => {
              item.addEventListener('click', function(event) {
                const li = document.createElement('li');
                li.innerText = "Nuevo elemento, el evento no funcionará en este";
                list.appendChild(li);
                alert(`Has hecho clic en: ${event.target.textContent}`);
              });
            });
          </script>
        </body>
      </html>
    
  

Problema: si la lista de elementos se aumenta dinámicamente, necesitarás agregar manejadores a cada nuevo elemento.

Solución — ejemplo con delegación de eventos:

HTML
    
      <!DOCTYPE html>
      <html>
        <head>
          <title>Ejemplo de delegación de eventos</title>
        </head>
        <body>
          <ul id="list">
            <li>Elemento 1</li>
            <li>Elemento 2</li>
            <li>Elemento 3</li>
          </ul>
          <script>
            const list = document.getElementById('list');
            list.addEventListener('click', function(event) {
              if (event.target.tagName === 'LI') {
                const li = document.createElement('li');
                li.innerText = "Nuevo elemento, el evento funcionará aquí";
                list.appendChild(li);
                alert(`Has hecho clic en: ${event.target.textContent}`);
              }
            });
          </script>
        </body>
      </html>
    
  

Ventajas:

  • El manejador se añade solo al elemento padre
  • Los elementos añadidos dinámicamente automáticamente soportarán el manejador de eventos

9.2 Prevención de manejadores innecesarios

Para evitar la disminución del rendimiento, es importante minimizar el número de manejadores de eventos, especialmente si están vinculados a muchos elementos o se invocan con frecuencia. Varios enfoques para la optimización:

1. Reducción del número de manejadores: usa la delegación de eventos para minimizar el número de manejadores.

2. Uso de once en addEventListener: si el manejador de eventos debe ejecutarse solo una vez, utiliza la opción { once: true } al añadir el manejador.

Ejemplo:

HTML
    
      <!DOCTYPE html>
      <html>
        <head>
          <title>Ejemplo de evento único</title>
        </head>
        <body>
          <button id="myButton">¡Haz clic en mí!</button>
          <script>
            const button = document.getElementById('myButton');
            button.addEventListener('click', function(event) {
              alert('Has hecho clic en el botón');
            }, { once: true });
          </script>
        </body>
      </html>
    
  

3. Debounce y throttling: estas técnicas son útiles para optimizar manejadores de eventos que se invocan con frecuencia, como scroll o resize.

9.3 Debounce

El debounce combina múltiples llamadas consecutivas de una función en una sola, que se ejecuta solo después de que el flujo de eventos ha cesado.

Ejemplo:

JavaScript
    
      function debounce(func, wait) {
        let timeout;
        return function(...args) {
          const context = this;
          clearTimeout(timeout);
          timeout = setTimeout(() => func.apply(context, args), wait);
        };
      }

      window.addEventListener('resize', debounce(() => {
        console.log('Ventana redimensionada');
      }, 300));
    
  

Intenta cambiar el ancho del widget para ver el resultado

Ejemplo de debounce

En este ejemplo, la función de búsqueda se llama solo después de que el usuario ha dejado de escribir durante 300 milisegundos.

HTML
    
      <!DOCTYPE html>
      <html>
        <head>
          <title>Ejemplo de debounce</title>
        </head>
        <body>
          <div style="min-height: 55px">
            <input type="text" id="searchInput" placeholder="Empieza a escribir tu consulta...">
            <div id="results"></div>
          </div>

          <script>
            const searchInput = document.getElementById('searchInput');
            const results = document.getElementById('results');

            function debounce(func, delay) {
              let timeout;
              return function(...args) {
                clearTimeout(timeout);
                timeout = setTimeout(() => {
                  func.apply(this, args);
                }, delay);
              };
            }

            function performSearch(event) {
              const query = event.target.value;
              results.textContent = 'Buscando: ' + query;
              // Simulación de solicitud al servidor
              setTimeout(() => {
                results.textContent = 'Has buscado: ' + query;
              }, 500);
            }

            const debouncedSearch = debounce(performSearch, 300);

            searchInput.addEventListener('input', debouncedSearch);
          </script>
        </body>
      </html>
    
  
HTML
    
      <!DOCTYPE html>
      <html>
        <head>
          <title>Ejemplo de debounce</title>
        </head>
        <body>
          <input type="text" id="searchInput" placeholder="Empieza a escribir tu consulta...">
          <div id="results"></div>

          <script>
            const searchInput = document.getElementById('searchInput');
            const results = document.getElementById('results');

            function debounce(func, delay) {
              let timeout;
              return function(...args) {
                clearTimeout(timeout);
                timeout = setTimeout(() => {
                  func.apply(this, args);
                }, delay);
              };
            }

            function performSearch(event) {
              const query = event.target.value;
              results.textContent = 'Buscando: ' + query;
              // Simulación de solicitud al servidor
              setTimeout(() => {
                results.textContent = 'Has buscado: ' + query;
              }, 500);
            }

            const debouncedSearch = debounce(performSearch, 300);

            searchInput.addEventListener('input', debouncedSearch);
          </script>
        </body>
      </html>
    
  

9.4 Throttling

Trolling Throttling garantiza que la función se llamará no más de una vez en un periodo de tiempo especificado.

Ejemplo:

JavaScript
    
      function throttle(func, limit) {
        let inThrottle;
        return function(...args) {
          const context = this;
          if (!inThrottle) {
            func.apply(context, args);
            inThrottle = true;
            setTimeout(() => inThrottle = false, limit);
          }
        };
      }

      window.addEventListener('scroll', throttle(() => {
        console.log('Ventana desplazada');
      }, 300));
    
  

Otro ejemplo de throttling

En este ejemplo, el manejador de scroll se ejecuta no más de cada 200 milisegundos, lo que ayuda a prevenir la sobrecarga del navegador con eventos de scroll frecuentes.

HTML
    
      <!DOCTYPE html>
      <html>
        <head>
          <title>Ejemplo de throttling</title>
        </head>
        <body>
          <div id="scrollContainer" style="height: 200px; overflow-y: scroll;">
            <div style="height: 1000px;"></div>
          </div>
          <div id="status">Comienza a desplazarte para ver el efecto</div>

          <script>
            const scrollContainer = document.getElementById('scrollContainer');
            const status = document.getElementById('status');

            function throttle(func, limit) {
              let lastFunc;
              let lastRan;
              return function(...args) {
                const context = this;
                if (!lastRan) {
                  func.apply(context, args);
                  lastRan = Date.now();
                } else {
                  clearTimeout(lastFunc);
                  lastFunc = setTimeout(() => {
                    if ((Date.now() - lastRan) >= limit) {
                      func.apply(context, args);
                      lastRan = Date.now();
                    }
                  }, limit - (Date.now() - lastRan));
                }
              };
            }

            function handleScroll(event) {
              status.textContent = 'Desplazando... ' + new Date().toLocaleTimeString();
            }

            const throttledScroll = throttle(handleScroll, 200);

            scrollContainer.addEventListener('scroll', throttledScroll);
          </script>
        </body>
      </html>
    
  

9.5 Optimización de eventos con listeners pasivos

Los listeners de eventos pasivos (passive event listeners) se utilizan para mejorar el rendimiento, especialmente al manejar eventos de scroll (scroll). Cuando el manejador de eventos está configurado como pasivo, significa que no invocará preventDefault(), lo que permite al navegador optimizar el rendimiento.

Ejemplo:

JavaScript
    
      window.addEventListener('scroll', function(event) {
        console.log('Desplazando');
      }, { passive: true });
    
  
Comentarios
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION