CodeGym /Corso Java /Frontend SELF IT /Ottimizzazione degli eventi

Ottimizzazione degli eventi

Frontend SELF IT
Livello 42 , Lezione 3
Disponibile

9.1 Delegazione degli eventi

Lavorare con gli eventi in JavaScript può richiedere una gestione complessa per ottimizzare le prestazioni e migliorare l'architettura dell'applicazione.

Ottimizzare la gestione degli eventi in JavaScript è fondamentale per creare applicazioni web performanti, soprattutto quando si deve lavorare con un gran numero di elementi. In questo contesto, la delegazione degli eventi e la prevenzione di gestori superflui giocano un ruolo chiave.

La delegazione degli eventi è un pattern in cui il gestore degli eventi viene impostato sull'elemento padre, invece che su ogni singolo elemento figlio. Questo permette di gestire efficacemente gli eventi per un ampio numero di elementi figli, poiché il gestore viene chiamato solo una volta per il padre, e non per ogni elemento.

Esempio senza delegazione degli eventi:

HTML
    
      <!DOCTYPE html>
      <html>
        <head>
          <title>Esempio di delegazione degli eventi</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 = "Nuovo elemento, l'evento su cui non funzionerà";
                list.appendChild(li);
                alert(`Hai cliccato su: ${event.target.textContent}`);
              });
            });
          </script>
        </body>
      </html>
    
  

Problema: se l'elenco degli elementi aumenta dinamicamente, sarà necessario aggiungere gestori a ogni nuovo elemento.

Soluzione — esempio con delegazione degli eventi:

HTML
    
      <!DOCTYPE html>
      <html>
        <head>
          <title>Esempio di delegazione degli eventi</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 = "Nuovo elemento, l'evento su cui funzionerà";
                list.appendChild(li);
                alert(`Hai cliccato su: ${event.target.textContent}`);
              }
            });
          </script>
        </body>
      </html>
    
  

Vantaggi:

  • Il gestore viene aggiunto solo all'elemento padre
  • Gli elementi aggiunti dinamicamente supporteranno automaticamente il gestore degli eventi

9.2 Prevenzione dei gestori superflui

Per evitare un calo delle prestazioni, è importante minimizzare il numero di gestori degli eventi, soprattutto se sono collegati a molti elementi o vengono chiamati spesso. Alcuni approcci per l'ottimizzazione:

1. Riduzione del numero di gestori: utilizza la delegazione degli eventi per ridurre il numero di gestori.

2. Uso di once in addEventListener: se il gestore dell'evento deve essere eseguito solo una volta, usa l'opzione { once: true } quando aggiungi il gestore.

Esempio:

HTML
    
      <!DOCTYPE html>
      <html>
        <head>
          <title>Esempio di evento singolo</title>
        </head>
        <body>
          <button id="myButton">Premi su di me!</button>
          <script>
            const button = document.getElementById('myButton');
            button.addEventListener('click', function(event) {
              alert('Hai premuto il pulsante');
            }, { once: true });
          </script>
        </body>
      </html>
    
  

3. Debounce e Throttle: queste tecniche sono utili per ottimizzare i gestori degli eventi che vengono chiamati spesso, come scroll o resize.

9.3 Debounce

Il debounce combina diverse chiamate consecutive di una funzione in una sola, da eseguire solo quando il flusso di eventi è terminato.

Esempio:

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('Window resized');
      }, 300));
    
  

Prova a cambiare la larghezza del widget per vedere il risultato

Esempio di debounce

In questo esempio, la funzione di ricerca viene chiamata solo dopo che l'utente ha smesso di digitare per 300 millisecondi.

HTML
    
      <!DOCTYPE html>
      <html>
        <head>
          <title>Esempio di debounce</title>
        </head>
        <body>
          <div style="min-height: 55px">
            <input type="text" id="searchInput" placeholder="Inizia a digitare la query...">
            <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 = 'Ricerca: ' + query;
              // Simulazione della richiesta al server
              setTimeout(() => {
                results.textContent = 'Hai cercato: ' + query;
              }, 500);
            }

            const debouncedSearch = debounce(performSearch, 300);

            searchInput.addEventListener('input', debouncedSearch);
          </script>
        </body>
      </html>
    
  
HTML
    
      <!DOCTYPE html>
      <html>
        <head>
          <title>Esempio di debounce</title>
        </head>
        <body>
          <input type="text" id="searchInput" placeholder="Inizia a digitare la query...">
          <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 = 'Searching for: ' + query;
              // Simulazione della richiesta al server
              setTimeout(() => {
                results.textContent = 'Hai cercato: ' + query;
              }, 500);
            }

            const debouncedSearch = debounce(performSearch, 300);

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

9.4 Throttle

Throttling garantisce che la funzione venga chiamata non più di una volta in un intervallo di tempo specificato.

Esempio:

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('Window scrolled');
      }, 300));
    
  

Un altro esempio di throttle

In questo esempio, il gestore dello scroll viene chiamato non più spesso di ogni 200 millisecondi, il che aiuta a prevenire il sovraccarico del browser durante frequenti eventi di scroll.

HTML
    
      <!DOCTYPE html>
      <html>
        <head>
          <title>Esempio di throttle</title>
        </head>
        <body>
          <div id="scrollContainer" style="height: 200px; overflow-y: scroll;">
            <div style="height: 1000px;"></div>
          </div>
          <div id="status">Inizia a scorrere per vedere l'effetto</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 = 'Scrolling... ' + new Date().toLocaleTimeString();
            }

            const throttledScroll = throttle(handleScroll, 200);

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

9.5 Ottimizzazione degli eventi con i listener passivi

I listener passivi (passive event listeners) sono utilizzati per migliorare le prestazioni, soprattutto durante la gestione degli eventi di scroll (scroll). Quando il gestore dell'evento è impostato come passivo, significa che non richiamerà preventDefault(), permettendo al browser di ottimizzare le prestazioni.

Esempio:

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