Eventos são ações ou ocorrências que acontecem no navegador, como cliques, teclas pressionadas ou movimentos do mouse. Manipular eventos é essencial para criar páginas interativas. Nesta aula, vamos explorar como ouvir e responder a eventos no DOM usando JavaScript, dominando o método addEventListener, o objeto event, os principais tipos de eventos e como remover listeners quando necessário.

Compreender eventos é fundamental para o desenvolvimento web moderno. Eles permitem que seu código reaja a interações do usuário e a mudanças no estado da página, tornando a experiência dinâmica e responsiva.

addEventListener

O método addEventListener registra uma função (chamada de handler ou listener) para ser executada quando um evento específico ocorre em um elemento. Ele é a forma mais flexível e recomendada de associar eventos, pois permite múltiplos listeners para o mesmo evento e oferece controle sobre a fase de propagação (captura ou bolha).

Sintaxe básica:

elemento.addEventListener(tipo, funcao, opcoes);

Onde tipo é uma string com o nome do evento (ex: 'click'), funcao é a função callback que será chamada, e opcoes é um objeto opcional que pode incluir propriedades como capture, once e passive.

Exemplo prático:

const botao = document.querySelector('#meuBotao');
botao.addEventListener('click', function() {
  alert('Botão clicado!');
});

Você também pode passar uma função nomeada ou uma arrow function:

function handleClick() {
  console.log('Clicou!');
}
botao.addEventListener('click', handleClick);

// ou
botao.addEventListener('click', () => console.log('Clicou!'));

O terceiro parâmetro pode ser um objeto com opções. Por exemplo, once: true faz o listener ser executado apenas uma vez e depois removido automaticamente:

botao.addEventListener('click', () => alert('Uma vez só!'), { once: true });

Objeto event

Quando um evento ocorre, o navegador cria um objeto event que contém informações detalhadas sobre o evento. Esse objeto é passado automaticamente como argumento para a função listener. Você pode acessar propriedades como event.type (tipo do evento), event.target (elemento que disparou o evento), event.currentTarget (elemento ao qual o listener está associado) e muitas outras específicas de cada tipo.

Exemplo:

document.querySelector('button').addEventListener('click', function(event) {
  console.log('Tipo:', event.type);
  console.log('Target:', event.target);
  console.log('CurrentTarget:', event.currentTarget);
});

Propriedades comuns do objeto event:

  • type: string com o nome do evento (ex: 'click', 'keydown').
  • target: referência ao elemento que originou o evento (pode ser um filho se houver propagação).
  • currentTarget: elemento ao qual o listener foi registrado (não muda com propagação).
  • preventDefault(): método que cancela o comportamento padrão do evento (ex: evitar que um link navegue).
  • stopPropagation(): método que interrompe a propagação do evento para elementos pais.
  • clientX / clientY: coordenadas do mouse (para eventos de mouse).
  • key e code: tecla pressionada (para eventos de teclado).

Exemplo usando preventDefault:

const link = document.querySelector('a');
link.addEventListener('click', function(event) {
  event.preventDefault();
  console.log('Link clicado, mas não navegou.');
});

Tipos comuns

Existem dezenas de tipos de eventos. Os mais usados no dia a dia incluem:

  • Eventos de mouse: click, dblclick, mouseenter, mouseleave, mousemove, mousedown, mouseup.
  • Eventos de teclado: keydown, keyup, keypress (obsoleto, prefira keydown).
  • Eventos de formulário: submit, change, input, focus, blur.
  • Eventos de documento/window: DOMContentLoaded, load, resize, scroll, beforeunload.
  • Eventos de toque (mobile): touchstart, touchmove, touchend.

Exemplo com evento de teclado:

document.addEventListener('keydown', function(event) {
  console.log('Tecla pressionada:', event.key);
  if (event.key === 'Enter') {
    console.log('Enter foi pressionado!');
  }
});

Exemplo com evento de formulário:

const form = document.querySelector('form');
form.addEventListener('submit', function(event) {
  event.preventDefault();
  const dados = new FormData(form);
  console.log('Formulário enviado', Object.fromEntries(dados));
});

Removendo listeners

Para remover um listener, use o método removeEventListener. É importante que a função passada para remover seja a mesma referência da que foi adicionada. Por isso, funções anônimas não podem ser removidas a menos que você guarde a referência em uma variável.

Sintaxe:

elemento.removeEventListener(tipo, funcao, opcoes);

Exemplo:

function handleClick() {
  console.log('Clicou!');
}

botao.addEventListener('click', handleClick);

// Mais tarde...
botao.removeEventListener('click', handleClick);

Se você usou opções no addEventListener, deve passar as mesmas opções no removeEventListener. Caso contrário, a remoção pode não funcionar.

Exemplo com opções:

botao.addEventListener('click', handleClick, { capture: true });
botao.removeEventListener('click', handleClick, { capture: true }); // necessário passar o mesmo objeto

Remover listeners é importante para evitar vazamentos de memória, especialmente em Single Page Applications onde elementos são removidos e adicionados dinamicamente. Sempre remova listeners de elementos que serão destruídos.

Boas práticas

  • Use addEventListener em vez de atributos HTML on* (onclick) para manter a separação entre comportamento e marcação.
  • Prefira funções nomeadas ou arrow functions guardadas em variáveis se precisar remover o listener depois.
  • Use a opção passive: true para eventos como scroll e touchmove para melhorar performance (indica que você não chamará preventDefault).
  • Evite listeners excessivos; considere delegação de eventos quando muitos elementos similares precisam do mesmo comportamento.
  • Sempre chame preventDefault() quando necessário para evitar ações padrão indesejadas.

Referências

Exercícios

  1. Crie um botão em HTML e adicione um evento de clique que exiba um alerta com a mensagem 'Olá, mundo!'.

    ✓ Resposta:
    <button id="meuBotao">Clique aqui</button>
    
    <script>
      document.getElementById('meuBotao').addEventListener('click', function() {
        alert('Olá, mundo!');
      });
    </script>
  2. Adicione um listener a um campo de texto que exiba no console o valor digitado a cada tecla pressionada (use o evento 'input').

    ✓ Resposta:
    <input type="text" id="meuInput">
    
    <script>
      document.getElementById('meuInput').addEventListener('input', function(event) {
        console.log('Valor digitado:', event.target.value);
      });
    </script>
  3. Prevenha o comportamento padrão de um link e exiba no console o href do link.

    ✓ Resposta:
    <a href="https://example.com" id="meuLink">Exemplo</a>
    
    <script>
      document.getElementById('meuLink').addEventListener('click', function(event) {
        event.preventDefault();
        console.log('Href:', event.target.href);
      });
    </script>
  4. Adicione um listener de clique a um botão que execute apenas uma vez (use a opção once).

    ✓ Resposta:
    <button id="botaoUnico">Clique uma vez</button>
    
    <script>
      document.getElementById('botaoUnico').addEventListener('click', function() {
        alert('Este alerta aparece apenas uma vez!');
      }, { once: true });
    </script>
  5. Crie um listener de clique em um elemento pai (div) e, dentro dele, verifique se o clique foi em um botão específico (filho) usando event.target.

    ✓ Resposta:
    <div id="pai">
      <button id="filho">Clique em mim</button>
    </div>
    
    <script>
      document.getElementById('pai').addEventListener('click', function(event) {
        if (event.target && event.target.matches('button#filho')) {
          console.log('Clique no botão filho!');
        }
      });
    </script>