Introdução aos Eventos de Browser em JavaScript
Aprenda como funcionam os eventos de browser em JavaScript: três formas de adicionar handlers, addEventListener vs onclick, o objeto de evento e muito mais.
Dominando os Eventos de Browser em JavaScript
Um evento de browser é um sinal de que algo aconteceu na página — o usuário clicou em um botão, uma tecla foi pressionada, uma imagem terminou de carregar, a janela foi redimensionada. Reagir a esses sinais é o que transforma um documento estático em uma aplicação interativa.
Este guia explica o que são eventos, as três formas de escutá-los (e qual delas preferir), o que o objeto de evento oferece, como parar de escutar, e apresenta seis exemplos práticos e executáveis do mundo real. Se você é novo na linguagem, comece com a introdução ao JavaScript primeiro.
Entendendo os Eventos de Browser
Um evento é uma ação ou ocorrência que o browser detecta e permite que seu código responda. Os eventos se dividem em dois grandes grupos:
- Eventos orientados ao usuário — clicar com o mouse, digitar, mover o ponteiro, enviar um formulário.
- Eventos orientados ao sistema — a página terminar de carregar, uma imagem falhar ao carregar, uma animação CSS terminar, a janela ser redimensionada.
Tipos de Eventos
Aqui estão alguns dos eventos mais comuns, agrupados por categoria:
| Categoria | Eventos |
|---|---|
| Mouse | click, dblclick, mouseover, mouseout, mousedown, mouseup |
| Teclado | keydown, keyup (keypress está obsoleto) |
| Formulário | submit, change, input, focus, blur |
| Documento / janela | DOMContentLoaded, load, resize, scroll, beforeunload |
Cada categoria tem seu próprio capítulo dedicado: veja eventos de mouse, eventos de teclado, eventos de envio de formulário e eventos de carregamento de recursos.
Três Formas de Adicionar Event Handlers
Existem três formas de reagir a um evento. Elas estão listadas da menos para a mais flexível.
1. Atributo HTML (onclick="...") — rápido, mas mistura JavaScript na sua marcação e permite apenas um handler. Evite em projetos reais.
<button onclick="alert('Button clicked!')">Click Me!</button>2. Propriedade DOM (element.onclick) — mantém o código em JavaScript, mas atribuir um novo handler sobrescreve o anterior, portanto ainda permite apenas um handler por evento.
<button id="myButton">Click Me!</button>document.getElementById('myButton').onclick = function () {
alert('Button clicked!');
};3. addEventListener (recomendado) — a abordagem padrão. Você pode anexar vários handlers para o mesmo evento, controlar a fase de captura/borbulhamento e remover o handler posteriormente.
<button id="myButton">Click Me!</button>document.getElementById('myButton').addEventListener('click', function () {
alert('Button clicked!');
});addEventListener é preferido porque permite registrar múltiplos listeners para o mesmo evento e oferece controle mais fino sobre o tratamento de eventos — por exemplo, chamando event.stopPropagation() ou event.preventDefault(). Ele também aceita um object de opções: { once: true } executa o handler uma única vez, e { capture: true } escuta durante a fase de captura (veja bubbling e capturing).
Removendo um Event Listener
Um listener permanece anexado até que você o remova (ou o elemento seja coletado pelo garbage collector). Para removê-lo, você deve passar a mesma referência de função que foi adicionada — uma função anônima inline não pode ser removida porque não há referência a ela.
function handleClick() {
console.log('clicked');
}
const btn = document.getElementById('myButton');
btn.addEventListener('click', handleClick);
// later — stops the handler from firing again
btn.removeEventListener('click', handleClick);O Objeto de Evento
Quando um evento é disparado, o browser cria um objeto de evento descrevendo o que aconteceu e o passa como primeiro argumento para o seu handler. Propriedades úteis incluem:
event.type— o nome do evento, por exemplo"click".event.target— o elemento que efetivamente disparou o evento.event.currentTarget— o elemento ao qual o listener está anexado (igual athisem um handler de função regular).event.preventDefault()— cancela a ação padrão do browser (por exemplo, seguir um link).event.stopPropagation()— impede que o evento borbulhe para elementos ancestrais.
<button id="myButton">Click Me!</button>
<div style="margin-top:10px;" id="eventInfo"></div>
<script>
document.getElementById('myButton').addEventListener('click', function(event) {
var eventInfo = 'Event Type: ' + event.type + '<br />Clicked Element: ' + event.target.tagName;
document.getElementById('eventInfo').innerHTML = eventInfo;
});
</script>Exemplos Práticos de Tratamento de Eventos de Browser
Vamos explorar alguns exemplos práticos que mostram como tratar eventos de browser em cenários do mundo real.
Exemplo 1: Evento de Envio de Formulário
Tratando o envio de um formulário para validar a entrada antes de enviar dados ao servidor:
<form id="loginForm">
Username: <input type="text" name="username" required />
Password: <input type="password" name="password" required />
<button type="submit">Login</button>
</form>
<script>
document.getElementById('loginForm').addEventListener('submit', function(event) {
event.preventDefault(); // Prevent the form from submitting normally
if (this.username.value.length < 4 || this.password.value.length < 4) {
alert('Username and password must be at least 4 characters long.');
} else {
this.submit(); // Submit the form manually if validation passes
alert('successfully submitted');
}
});
</script>(Nota: Uma função regular é usada aqui em vez de uma arrow function para preservar o contexto de this, permitindo que this.username e this.password referenciem corretamente os elementos do formulário.)
Exemplo 2: Tratando Eventos Mouse Over e Mouse Out
Alterando o estilo de um botão quando o mouse está sobre ele e redefinindo quando o mouse sai:
<button id="hoverButton">Hover Over Me!</button>
<script>
const button = document.getElementById('hoverButton');
button.addEventListener('mouseover', function() {
this.style.backgroundColor = 'green';
});
button.addEventListener('mouseleave', function() {
this.style.backgroundColor = '';
});
</script>Exemplo 3: Eventos de Teclado
Executando uma função quando a tecla Enter é pressionada:
<input type="text" id="inputField" placeholder="Type something and press Enter" />
<script>
document.getElementById('inputField').addEventListener('keydown', function(event) {
if (event.key === 'Enter') {
alert('You pressed Enter!');
}
});
</script>Exemplo 4: Funcionalidade de Arrastar e Soltar
Implementando arrastar e soltar para uma transferência simples de imagem dentro de uma página web:
<span>Drop image below</span>
<div id="dragArea" style="width: 300px; height: 300px; border: 2px dashed #ccc;">
</div>
<img id="draggableImage" src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='150' height='150'%3E%3Crect width='150' height='150' fill='%234f46e5'/%3E%3Ctext x='75' y='80' fill='white' font-size='18' text-anchor='middle'%3EDrag me%3C/text%3E%3C/svg%3E" draggable="true" style="width: 150px; height: 150px;">
<script>
const dragArea = document.getElementById('dragArea');
const draggableImage = document.getElementById('draggableImage');
// Event listener for the drag start
draggableImage.addEventListener('dragstart', function(event) {
event.dataTransfer.setData("text/plain", event.target.id);
});
// Event listener for dragging over the drag area
dragArea.addEventListener('dragover', function(event) {
event.preventDefault(); // Necessary to allow the drop
});
// Event listener for drop
dragArea.addEventListener('drop', function(event) {
event.preventDefault(); // Prevent default behavior (like opening as link for some elements)
const data = event.dataTransfer.getData("text/plain");
const image = document.getElementById(data);
dragArea.appendChild(image);
});
</script>Explicação:
- Início do Arraste: Quando você começa a arrastar a imagem, o ID da imagem é salvo nos dados de arrastar.
- Arraste Sobre: Impedir a ação padrão é necessário para permitir o soltar.
- Soltar: Ao soltar, a imagem é movida para a área de destino.
Exemplo 5: Eventos de Início e Fim de Animação
Usando animações CSS e tratando seu início e fim com JavaScript:
<div id="animateBox" style="width: 100px; height: 100px; background: red; position: relative; animation: moveBox 5s 2;"></div>
<div id="animationStatus"></div>
<style>
@keyframes moveBox {
0% { left: 0; }
50% { left: 200px; }
100% { left: 0; }
}
</style>
<script>
const box = document.getElementById('animateBox');
const statusDisplay = document.getElementById('animationStatus');
box.addEventListener('animationstart', function() {
statusDisplay.innerHTML = 'Animation started';
});
box.addEventListener('animationend', function() {
statusDisplay.innerHTML = 'Animation ended';
});
box.addEventListener('animationiteration', function() {
statusDisplay.innerHTML = 'Animation iteration';
});
</script>(Nota: animationstart e eventos relacionados são padrão nos browsers modernos. Versões mais antigas do Safari podem exigir prefixos de fabricante como -webkit-animationstart, mas os nomes padrão são recomendados para o desenvolvimento atual.)
Explicação:
animationstarté disparado uma vez quando a animação começa.animationiterationé disparado no início de cada repetição — útil quando uma animação está configurada para ser executada várias vezes.animationendé disparado uma vez quando a animação termina. A div#animationStatusé atualizada em cada evento para fornecer feedback em tempo real na página.
Exemplo 6: Eventos Personalizados
Criando e despachando eventos personalizados para tratar cenários específicos da aplicação:
<button id="customEventButton">Trigger Custom Event</button>
<script>
// Creating a custom event
const myEvent = new CustomEvent('myCustomEvent', {
detail: { message: 'Custom event triggered' }
});
// Event listener for custom event
document.addEventListener('myCustomEvent', function(event) {
alert('Event Message: ' + event.detail.message);
});
// Dispatch the custom event when button is clicked
document.getElementById('customEventButton').addEventListener('click', function() {
document.dispatchEvent(myEvent);
});
</script>Explicação:
- Criação do Evento Personalizado: Define um evento personalizado com dados adicionais (
detailcontendo uma mensagem). - Tratamento do Evento: Configura um listener para o evento personalizado que exibe um alerta com a mensagem do detalhe do evento.
- Disparo do Evento: Dispara o evento personalizado ao clicar no botão.
Boas Práticas
- Prefira
addEventListenerem vez de atributosonclickinline — mantém o comportamento fora da sua marcação e suporta múltiplos handlers. - Use funções regulares quando precisar que
thisse refira ao elemento; use arrow functions quando não precisar, e leiaevent.currentTargetem vez disso. - Remova listeners que você não precisa mais com
removeEventListener(passando a mesma referência de função) para evitar vazamentos de memória, especialmente em aplicações de página única. - Anexe um listener a um elemento pai em vez de muitos a cada filho ao lidar com listas — essa técnica, chamada de delegação de eventos, baseia-se no event bubbling.
- Limite a frequência de eventos de alta frequência como
scrolleresizepara evitar executar trabalho custoso a cada disparo; veja otimização de desempenho do DOM.
Conclusão
Os eventos de browser são a ponte entre o que o usuário faz e como seu código responde. Os pontos principais: use addEventListener para flexibilidade, leia o que você precisa do objeto de evento, chame preventDefault() ou stopPropagation() quando precisar substituir o comportamento padrão, e remova listeners que você não precisa mais.
A partir daqui, explore os capítulos dedicados sobre eventos de mouse, eventos de teclado, tratamento de envio de formulários e despacho de eventos personalizados para criar interfaces mais ricas e orientadas a eventos.