CodeGym /Cursos /Frontend SELF PT /Otimização de Eventos

Otimização de Eventos

Frontend SELF PT
Nível 42 , Lição 3
Disponível

9.1 Delegação de Eventos

Trabalhar com eventos em JavaScript pode exigir uma gestão complexa para otimizar o desempenho e melhorar a arquitetura do aplicativo.

Otimizar o trabalho com eventos em JavaScript é crucial para criar aplicações web de alta performance, especialmente quando se lida com um grande número de elementos. Nesse contexto, a delegação de eventos e a prevenção de handlers desnecessários desempenham um papel fundamental.

Delegação de eventos é um padrão onde o handler do evento é definido no elemento pai, em vez de cada elemento filho individual. Isso permite gerenciar eventos de maneira eficiente para um grande número de elementos filhos, já que o handler é chamado apenas uma vez para o pai, ao invés de para cada elemento.

Exemplo sem delegação de eventos:

HTML
    
      <!DOCTYPE html>
      <html>
        <head>
          <title>Exemplo de Delegação 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 = "Novo elemento, evento não funcionará";
                list.appendChild(li);
                alert(`Você clicou em: ${event.target.textContent}`);
              });
            });
          </script>
        </body>
      </html>
    
  

Problema: se a lista de elementos aumentar dinamicamente, será necessário adicionar handlers para cada novo elemento.

Solução — exemplo com delegação de eventos:

HTML
    
      <!DOCTYPE html>
      <html>
        <head>
          <title>Exemplo de Delegação 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 = "Novo elemento, evento funcionará";
                list.appendChild(li);
                alert(`Você clicou em: ${event.target.textContent}`);
              }
            });
          </script>
        </body>
      </html>
    
  

Vantagens:

  • Handler é adicionado apenas ao elemento pai
  • Elementos adicionados dinamicamente automaticamente suportarão o handler de eventos

9.2 Prevenção de Handlers Desnecessários

Para evitar a degradação de performance, é importante minimizar a quantidade de handlers de eventos, especialmente se eles estão anexados a muitos elementos ou são frequentemente chamados. Algumas abordagens para otimização:

1. Diminuição da quantidade de handlers: use delegação de eventos para reduzir o número de handlers.

2. Uso de once em addEventListener: se o handler de evento só precisar funcionar uma vez, use a opção { once: true } ao adicionar o handler.

Exemplo:

HTML
    
      <!DOCTYPE html>
      <html>
        <head>
          <title>Exemplo de Evento Único</title>
        </head>
        <body>
          <button id="myButton">Clique em mim!</button>
          <script>
            const button = document.getElementById('myButton');
            button.addEventListener('click', function(event) {
              alert('Você clicou no botão');
            }, { once: true });
          </script>
        </body>
      </html>
    
  

3. Debouncing e Throttling: essas técnicas são úteis para otimizar handlers de eventos que são frequentemente chamados, como scroll ou resize.

9.3 Debouncing

Debouncing combina múltiplas chamadas consecutivas de uma função em uma única, executada apenas após a interrupção do fluxo de eventos.

Exemplo:

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('Janela redimensionada');
      }, 300));
    
  

Experimente mudar a largura do widget para ver o resultado

Exemplo de Debouncing

Neste exemplo, a função de busca é chamada apenas depois que o usuário para de digitar por 300 milissegundos.

HTML
    
      <!DOCTYPE html>
      <html>
        <head>
          <title>Exemplo de Debouncing</title>
        </head>
        <body>
          <div style="min-height: 55px">
            <input type="text" id="searchInput" placeholder="Comece a digitar sua 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;
              // Simulação de requisição ao servidor
              setTimeout(() => {
                results.textContent = 'Você procurou por: ' + query;
              }, 500);
            }

            const debouncedSearch = debounce(performSearch, 300);

            searchInput.addEventListener('input', debouncedSearch);
          </script>
        </body>
      </html>
    
  
HTML
    
      <!DOCTYPE html>
      <html>
        <head>
          <title>Exemplo de Debouncing</title>
        </head>
        <body>
          <input type="text" id="searchInput" placeholder="Comece a digitar sua 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 por: ' + query;
              // Simulação de requisição ao servidor
              setTimeout(() => {
                results.textContent = 'Você procurou por: ' + query;
              }, 500);
            }

            const debouncedSearch = debounce(performSearch, 300);

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

9.4 Throttling

Trolling Throttling garante que a função seja chamada não mais do que uma vez em um determinado intervalo de tempo.

Exemplo:

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('Janela rolada');
      }, 300));
    
  

Outro exemplo de Throttling

Neste exemplo, o handler de rolagem é chamado no máximo a cada 200 milissegundos, o que ajuda a evitar sobrecarregar o navegador com eventos de rolagem frequentes.

HTML
    
      <!DOCTYPE html>
      <html>
        <head>
          <title>Exemplo de Throttling</title>
        </head>
        <body>
          <div id="scrollContainer" style="height: 200px; overflow-y: scroll;">
            <div style="height: 1000px;"></div>
          </div>
          <div id="status">Comece a rolar para ver o efeito</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 = 'Rolando... ' + new Date().toLocaleTimeString();
            }

            const throttledScroll = throttle(handleScroll, 200);

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

9.5 Otimização de Eventos com Listeners Passivos

Listeners passivos de eventos (passive event listeners) são usados para melhorar o desempenho, especialmente quando processando eventos de rolagem (scroll). Quando um handler de evento é definido como passivo, isso significa que ele não chamará preventDefault(), permitindo que o navegador otimize o desempenho.

Exemplo:

JavaScript
    
      window.addEventListener('scroll', function(event) {
        console.log('Rolando');
      }, { passive: true });
    
  
1
Tarefa
Frontend SELF PT, nível 42, lição 3
Bloqueado
Debouncing de entrada
Debouncing de entrada
1
Tarefa
Frontend SELF PT, nível 42, lição 3
Bloqueado
Trotleamento de rolagem
Trotleamento de rolagem
Comentários
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION