Guia para manipular eventos no DOM com JavaScript: técnicas e exemplos práticos
Imagine que você está coordenando uma equipe de desenvolvimento em uma empresa de tecnologia.
Cada dev é responsável por uma parte importante do aplicativo mobile e cada linha de código é um evento que precisa ser gerenciado para criar uma experiência de usuário fluida e suave.
Ao interagir com o aplicativo, a pessoa usuária desencadeia uma série de eventos que devem ser coordenados para garantir uma navegação fluida e intuitiva.
Neste artigo, vamos explorar o incrível mundo dos eventos do DOM (Document Object Model). Caso queira entender mais sobre o que é o DOM, você pode acessar este artigo.
Exploraremos:
- O que são eventos do DOM;
- Os principais eventos, como cliques, movimentos de mouse, teclado e eventos de formulário;
- Maneiras de adicionar e remover os eventos em nosso código;
- Exemplos de como usar os eventos do DOM para criar páginas interativas e dinâmicas;
- Dicas de como usar da melhor maneira os eventos do DOM.
Preparado para coordenar os eventos e criar sua própria página dinâmica?
O que são os eventos do DOM?
Podemos dizer que os eventos em JavaScript são ações que ocorrem no navegador, como um clique do mouse, o pressionamento de alguma tecla ou até mesmo o carregamento de uma página.
Tais ações podem ser capturadas pelo navegador e manipuladas para garantir uma interação mais dinâmica com a página web.
Como associar eventos aos elementos HTML?
Há duas maneiras principais de associar eventos aos elementos HTML, a primeira delas é utilizar o atributo on
diretamente na tag dentro do arquivo HTML.
Por exemplo, podemos associar a função botaoClicado
, definida em JavaScript para exibir um alerta com a mensagem "Botão Clicado!", ao evento de click
de um botão adicionando o atributo onclick
da seguinte maneira:
<button onclick="botaoClicado()">Clique aqui </button>
A segunda maneira é usar métodos do próprio JavaScript de adição e remoção de eventos como o addEventListener
e o removeEventListener
.
Ambos permitem maior flexibilidade para lidar com eventos do DOM. Além disso, dessa maneira mantemos a lógica de programação e toda a dinamicidade que estamos usando na aplicação em apenas um documento, neste o arquivo que contém a linguagem JavaScript.
Estrutura básica de um evento
Para entender melhor como os eventos funcionam no DOM, precisamos conhecer a estrutura básica que envolve: Event Target, Event Listener e Event Handler.
Event Target
O Event Target é o elemento onde o evento vai acontecer. Por exemplo, a tag <button>
no HTML, uma imagem, um link ou até mesmo a própria janela do navegador.
Pensemos em um botão onde a pessoa usuária pode clicar, ao realizar esse clique o evento é disparado.
<button id="meu-botao"> Clique aqui </button>
Event Listener
O Event Listener é a função que aguarda até que um evento ocorra em um elemento. Adicionamos um Event Listener através do método addEventListener
, que vai ficar alerta para qualquer evento que aconteça.
Por exemplo, podemos adicionar um Event Listener no botão para que ao clicar nele, seja retornado um alerta com a mensagem "Botão clicado!".
let button = document.getElementById('meu-botao');
button.addEventListener('click', () => {
alert('Botão clicado!');
});
Event Handler
O Event Handler é a ação, representada por uma função ou código, que ocorre em resposta ao evento.
No exemplo anterior, a função de seta (arrow function) que exibe o alerta "Botão clicado!" é o Event Handler.
Contudo, o Event Handler também pode ser uma função definida separadamente. Caso queira saber a diferença entre uma arrow function e uma função definida separadamente, este artigo trará muitas informações interessantes que irão te ajudar a entender melhor sobre esse assunto.
function exibirMensagem() {
alert('Botão clicado!');
}
let button = document.getElementById('meu-botao');
button.addEventListener('click', exibirMensagem);
Com o conhecimento da estrutura dos eventos, podemos definir o fluxo de eventos da seguinte forma:
- Uma ação ocorre, como o clique de um botão e um evento é acionado.
- O Event Listener registrado para esse tipo de evento no elemento especificado ouve o evento.
- Quando o evento é detectado, a função associada é executada.
Tipos de Eventos no DOM
Há vários tipos de eventos no DOM, como o evento de clique que exploramos anteriormente.
Agora vamos conhecer outros tipos de eventos que podemos usar em nossas aplicações.
Evento de click
Esse evento acontece quando o usuário clica em um elemento da página. Suponha que temos um botão no arquivo "index.html"
<!DOCTYPE html>
<html lang="pt-Br">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Evento de clique</title>
</head>
<body>
<button id="meu-botao">Clique aqui</button>
<script src="main.js"></script>
</body>
</html>
Queremos que ao clicar neste botão o usuário receba um alerta "Botão clicado!". Para isso podemos criar no arquivo "main.js" o seguinte código:
var botao = document.querySelector("#meu-botao")
botao.addEventListener('click', () => {
alert('Botão clicado!');
})
Neste código estamos capturando o elemento com id meu-botao
e guardando este elemento em uma variável chamada botão.
Nesta variável, adicionamos um ouvinte de eventos por meio do addEventListener
que vai aguardar o clique do botão. Assim que o botão for clicado, ele vai exibir o alerta "Botão clicado!".
Evento de dblclick
Este evento é disparado quando o botão principal do mouse for clicado duas vezes rapidamente.
Por exemplo, temos um cartão com algumas informações no nosso arquivo "index.html":
<!DOCTYPE html>
<html lang="pt-Br">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="style.css"/>
<title>Evento de clique duplo</title>
</head>
<body>
<aside>
<h3>Meu cartão</h3>
<p>Clique duas vezes para redimensionar o tamanho do cartão.</p>
</aside>
<script src="main.js"></script>
</body>
</html>
Queremos redimensionar o cartão quando clicamos duas vezes dentro dele. Para isso precisamos definir o estilo para o cartão em um arquivo "style.css" e como ele deve ficar após o redimensionamento.
aside {
background: #fe9;
border-radius: 1em;
display: inline-block;
padding: 1em;
transform: scale(0.9);
transform-origin: 0 0;
transition: transform 0.6s;
user-select: none;
}
.large {
transform: scale(1.3);
}
O código acima, estiliza o elemento <aside>
com um fundo amarelo, bordas arredondadas, e uma escala inicial reduzida de 90% com transição suave ao aumentar para 130% quando adicionamos a classe large
.
A transformação se origina no canto superior esquerdo, e a seleção de texto é desativada.
Por fim, para realizar esse redimensionamento, vamos usar o seguinte código no arquivo "main.js".
var cartao = document.querySelector("aside");
cartao.addEventListener("dblclick", () => {
cartao.classList.toggle("large");
});
Neste código, guardamos na variável cartao
o elemento que queremos redimensionar e aplicamos um ouvinte de eventos nele, que vai aguardar até que um clique duplo seja feito para aplicar a classe large
ao elemento por meio do classList
, note que também usamos o toggle
para quando alternar entre o estilo original e o estilo redimensionado.
Evento de mouseover
Este evento acontece quando o cursor do mouse passa por cima de um elemento da página. Suponha que você tem uma lista com três itens no seu arquivo "index.html".
<!DOCTYPE html>
<html lang="pt-Br">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Evento de mouseover</title>
</head>
<body>
<ul id="lista">
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
</ul>
<script src="main.js"></script>
</body>
</html>
Queremos que ao passar o mouse por cima de um dos itens a cor do item seja alterada. Para isso, podemos colocar o seguinte código no arquivo "main.js":
var lista = document.querySelector("#lista");
lista.addEventListener("mouseover", (event)=>{
event.target.style.color = "orange";
setTimeout(() => {
event.target.style.color = "";
}, 500);
})
Neste código, adicionamos à lista um ouvinte de eventos que aguarda até que o cursor do mouse passe por cima de um dos itens da lista.
Assim que essa ação acontece, o alvo do evento tem sua cor alterada para laranja por meio do código event.target.style.color="orange"
por um período determinado de tempo, cerca de meio segundo, definido através da função setTimeout
.
Eventos de keydown
e keyup
Ambos os eventos estão relacionados as teclas do teclado.
O evento de keydown
acontece no momento em que a tecla é pressionada. Um evento similar é o keypress
que tem o mesmo objetivo, mas se tornou obsoleto.
A principal diferença entre eles é que o evento de keydown
é disparado para todas as chaves, independentemente de elas produzirem um valor de caractere.
Por outro lado, o evento de keyup
é disparado quando a tecla que foi pressionada é liberada, ou seja, no momento em que a tecla é solta a função é acionada.
Para entender a diferença entre estes eventos de maneira prática vamos supor que queremos criar um programa que conta quantas vezes uma tecla é clicada.
O código abaixo, apresenta a estrutura básica de um arquivo HTML e na dentro da tag <body>
há uma tag de título com a frase "Contador de teclas" e uma tag <span>
que contem inicialmente o valor zero.
<!DOCTYPE html>
<html lang="pt-Br">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Eventos de tecla</title>
</head>
<body>
<h1>Contador de teclas</h1>
<span id="paragrafo">0</span>
<script src="main.js"></script>
</body>
</html>
Agora vamos ver como a contagem acontece quando temos o evento de keydown
e de keyup
aplicados ao código JavaScript.
Para criar o código que usa o evento de keydown
, definimos duas variáveis, a contador
que guarda o valor da tag <span>
e a keyDownCount
que se inicia com o valor zero.
No documento HTML, adicionamos um ouvinte de eventos que aguarda até que uma tecla seja pressionada.
Assim que esta ação ocorre, o valor da variável keyDownCount
é incrementado em uma unidade e o valor de vezes que a tecla é pressionado é exibido na tela por meio do textContent
aplicado à variável contador
.
var contador = document.querySelector("#paragrafo")
var keyDownCount = 0
document.addEventListener("keydown", ()=>{
keyDownCount++
contador.textContent=keyDownCount
})
No exemplo, assim que a tecla é pressionada o contador é assionado e o valor é incrementado e caso a tecla continue sendo pressionada o valor continuará sendo incrementado até que a tecla seja solta.
Já para criar o código que usa o evento de keyup
, também definimos duas variáveis, a contador
que guarda o valor da tag <span>
e a keyUpCount
que se inicia com o valor zero.
No documento HTML, adicionamos um ouvinte de eventos que aguarda até que uma tecla que foi pressionada seja solta.
Assim que esta ação ocorre, o valor da variável keyUpCount
é incrementado em uma unidade e o valor de vezes que a tecla é solta é exibido na tela por meio do textContent
aplicado à variável contador
.
var contador = document.querySelector("#paragrafo")
var keyUpCount = 0
document.addEventListener("keyup", ()=>{
keyUpCount++
contador.textContent=keyDownCount
})
Nesta outra situação, apenas quando soltamos a tecla que foi pressionada o valor da contagem é aumentado, portanto, mesmo que mantenhamos a tecla pressionada por algum tempo, não será incrementado o valor na variável contador
como acontece ao utilizar o keydow
.
Para entender onde usar cada um dos dois eventos podemos pensar da seguinte maneira:
Use keydown para:
- Detectar a pressão inicial de uma tecla;
- Executar uma ação imediatamente ao pressionar a tecla;
- Capturar e segurar a tecla, como em jogos onde o personagem deve se mover enquanto a tecla é mantida pressionada;
- Obter respostas rápidas, por exemplo, para capturar as teclas repetidamente enquanto estão pressionadas.
Use keyup para:
- Detectar quando uma tecla é solta;
- Executar uma ação após a tecla ser liberada;
- Capturar sequências de teclas e precisa saber o momento exato em que a tecla é liberada;
- Evitar múltiplas execuções de uma ação enquanto a tecla está pressionada.
Evento de submit
O evento submit
é disparado quando um formulário é submetido. Por padrão, ao submeter um formulário, a página é automaticamente recarregada.
Por exemplo, experimente copiar o código abaixo no seu arquivo "index.html" e note que ao preencher os campos e enviar o formulário o ícone no topo superior esquerdo da página ao lado do campo com a URL do site que indica o recarregamento da página é acionado.
<!DOCTYPE html>
<html lang="pt-Br">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Evento de submit</title>
</head>
<body>
<form id="meu-formulario">
<input id="email" type="text" placeholder="E-mail">
<input id="senha" type="text" placeholder="Senha">
<button type="submit">Submeter o formulário</button>
</form>
<script src="main.js"></script>
</body>
</html>
Podemos evitar o comportamento padrão através do método preventDefault()
associado ao evento que não queremos que aconteça, neste caso o recarregamento da página.
Além disso, também conseguimos associar outras ações para a ocorrência da submissão do formulário, como a exibição de um alerta com a mensagem "Formulário Enviado!".
Para isso, podemos usar o seguinte código no arquivo "main.js":
var formulario = document.querySelector('#meu-formulario')
formulario.addEventListener("submit", (event) =>{
event.preventDefault();
alert('Formulário enviado!');
})
No código, perceba que inicialmente foi adicionado um ouvidor de eventos que aguarda até que uma submissão de formulário seja feita.
A partir do momento que essa ação acontece, há o desencadeamento de um evento que previne o recarregamento da página e a exibição do alerta com a mensagem escolhida em substituição da ação padrão.
Evento de focus
Este evento é disparado quando um elemento recebe foco. Vamos manter o exemplo de código que usamos para o arquivo HTML ao abordarmos o evento de submit
.
Ao clicarmos nos campos de preenchimento de e-mail ou senha, estamos colocando sobre eles um foco, que pode ser destacado através do uso deste método.
Neste caso, queremos adicionar uma cor azul-clara no campo referente ao email e uma cor rosa-clara no campo referente a senha. Para isso, podemos adotar o seguinte código:
var email = document.querySelector("#email");
var senha = document.querySelector("#senha")
email.addEventListener("focus", (event)=>{
event.target.style.background = "lightblue";
});
senha.addEventListener("focus", (event) =>{
event.target.style.background="lightpink"
})
O código adiciona um ouvinte de eventos que espera até que um dos campos seja clicado, caso seja o campo de email a cor de fundo do input
ficará azul-claro, caso seja o campo de senha a cor de fundo do input
ficará rosa-claro.
Isso ocorre, pois adicionamos ao alvo do evento, neste caso cada um dos campos, um estilo de cor de fundo por meio do trecho de código event.target.style.background
.
Contudo, vale ressaltar que a ação gerada ao usar este evento é uma via única, ou seja, após clicar dentro do campo de email e/ou senha e dar foco neles, qualquer outra ação que seja feita como, clicar fora do campo ou em outra parte do código não vai desfazer a ação gerada pelo evento focus
, sendo assim, a cor que aplicamos no exemplo acima continuará presente.
Para isso, podemos usar de forma associada ao evento de focus
o evento de blur
que será o próximo tópico explorado.
Evento de blur
Ao contrário do evento de focus
, o evento de blur
acontece quando um elemento perde o foco, ou seja, em um campo de preenchimento, quando clicamos fora do campo ou em outro elemento, aquele que estava em destaque perde o foco.
Usaremos como exemplo o mesmo código HTML que estamos aplicando tanto para o submit
quanto para o focus
, contudo, acrescentamos um trecho de código no arquivo JavaScript para que ao deixar o foco a cor azul-clara e a cor rosa-clara desapareçam. Ficaria assim:
var email = document.querySelector("#email");
var senha = document.querySelector("#senha")
email.addEventListener("focus", (event)=>{
event.target.style.background = "lightblue";
});
senha.addEventListener("focus", (event) =>{
event.target.style.background="lightpink"
})
email.addEventListener("blur", (event)=>{
event.target.style.background = "";
});
senha.addEventListener("blur", (event) =>{
event.target.style.background=""
})
Note que a estrutura do código é bem parecida com a que usamos para alterar a cor de fundo ao darmos foco em um input
, contudo a alteração está no tipo de evento e no campo vazio do alvo do evento.
Tanto o evento focus
quanto o evento blur
podem ser associados para garantir maior dinamicidade à página, permitindo a alternância entre campos que estão sendo focados e os que não estão.
Evento de change
Este evento, é disparado em tags como <input>
, <select>
e <textarea>
assim que a pessoa usuária altera o valor do elemento em um desses campos de preenchimento.
Por exemplo, no arquivo HTML, temos um campo de seleção onde podemos escolher o sabor de sorvete favorito:
<!DOCTYPE html>
<html lang="pt-Br">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Evento de change</title>
</head>
<body>
<label>
Escolha seu sabor de sorvete favorito!
<select id="sorvete" name="sorvete">
<option value="">Selecione um sabor:</option>
<option value="chocolate">Chocolate</option>
<option value="morango">Morango</option>
<option value="creme">Creme</option>
</select>
</label>
<div id="resultado"></div>
<script src="main.js"></script>
</body>
</html>
Ao selecionar uma opção, ela deve aparecer na tela e se, por acaso, mudarmos o sorvete favorito, queremos que a mensagem exibida na tela contendo o sabor escolhido seja modificada. Conseguimos fazer isso através do evento change
. Para isso, podemos usar o código abaixo:
var elementoSelecionado = document.querySelector("#sorvete");
var resultado = document.querySelector("#resultado");
elementoSelecionado.addEventListener("change", (event) => {
resultado.textContent = `Você escolheu ${event.target.value}`;
});
Selecionamos tanto as opções de sorvete quanto a tag <div>
onde a mensagem deve aparecer e guardamos em duas variáveis elementoSelecionado
e resultado
.
Adicionamos um ouvinte de eventos na variável elementoSelecionado
e assim que um dos sabores for selecionado, o resultado aparecerá na tela por meio do textContent
, onde o valor do alvo da seleção será exibido na tela através do código event.target.value
.
Quando alteramos a opção escolhida, a mensagem deve mudar devido ao tipo de evento selecionado.
Evento de load
Este evento é disparado quando os recursos usados na página forma completamente carregados. Por exemplo, temos em nosso documento HTML um título e um parágrafo com uma única frase:
<!DOCTYPE html>
<html lang="pt-br">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Evento de load</title>
</head>
<body>
<h1>Evento de load</h1>
<p>Texto da página</p>
<script src="main.js"></script>
</body>
</html>
Quando todos os elementos forem carregados na página, um alerta deverá aparecer na tela informando que a página foi carregada completamente.
Podemos fazer isso utilizando o objeto window
que representa toda a tela da página do navegador com todos os elementos presentes nela.
Neste objeto iremos adicionar um ouvinte de eventos que vai aguardar até que a página seja completamente carregada e vai exibir o alerta. Segue o código abaixo:
window.addEventListener('load', ()=>{
alert('Todos os recursos foram completamente carregados.')
});
Neste exemplo, assim que a página abrir, o alerta já será exibido, pois o carregamento dos elementos é feito rapidamente.
Contudo, caso a página tenha muitos recursos, pode ser que demore um pouco mais para que toda a página seja carregada e com isso o alerta pode demorar para ser exibido.
Dicas de como usar os eventos do DOM
Podemos adotar algumas práticas ao trabalhar com eventos em JavaScript para garantir que o código mantenha-se conciso, claro e eficiente, dentre elas podemos destacar:
- Separar a lógica de manipulação de eventos do arquivo HTML, ou seja, sempre que possível, devemos evitar a adição de manipuladores de eventos diretamente nos elementos HTML por meio do atributo
on
.
Ao invés disso, podemos preferir a adoção do método addEventListener
para adicionar ouvintes de eventos no documento JavaScript.
- Sempre que possível, adicionar um único manipulador de eventos ao elemento pai e verificar quais elementos filhos estão sendo manipulados por esse evento ao invés de adicionar separadamente um manipulador de eventos para cada elemento individualmente.
Com essa duas dicas, é possível melhorar a eficiência, manutenção e desempenho do código quando usamos eventos do DOM, garantindo uma aplicação mais concisa, eficiente e fluida.
Conclusão
Ufa! Exploramos bastante o mundo dos eventos em JavaScript. Entendemos melhor o que são essas ações e como elas podem ser manipuladas para criar um código mais dinâmico e interativo.
Além disso, compreendemos como associar esses eventos de duas formas distintas, sendo a primeira diretamente na tag do documento HTML, e a segunda por meio do método addEventListener
.
Também exploramos a estrutura dos eventos e aprendemos a delimitar um fluxo de como esse evento acontece desde o momento da primeira ação até a resposta que ele gera e com isso conhecemos mais sobre o Event Target, Event Listener e Event Handler.
Após toda essa parte mais teórico, tivemos contato com alguns tipos de evento que incluem: click
, dblclick
, mouseover
, keyup
, keydown
, submit
, focus
, blur
, load
e change
.
Todos inseridos em contextos de aplicações em código para exemplificar a finalidade de cada um.
Por fim vimos algumas dicas de como aplicar esses eventos de maneira mais clara e objetiva para garantir melhor desempenho, manutenção e eficiência no código.
Com certeza esse é apenas o começo e há muitos outros eventos que você pode explorar para manipular os elementos HTML utilizando a linguagem JavaScript para garantir uma melhor experiência de interatividade da pessoa usuária ao utilizar a página web.
Agora vamos colocar as mãos na massa para criar uma aplicação utilizando HTML, CSS e JavaScript que utilize o máximo de todos os eventos.
O desafio vai ser criar um formulário de cadastro que contenha três campos: nome, email e senha, nele você pode incorporar eventos de clique, clique duplo, submissão do formulário, campos com foco e sem foco, o load da página e outros que podem ser usados para deixar ainda mais interativa sua página.
Podem usar os códigos abaixo como base para desenvolver a parte dos eventos em JavaScript:
Arquivo HTML:
<!DOCTYPE html>
<html lang="pt-BR">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Desafio Eventos do DOM</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<form id="cadastroForm" class="container">
<h2>Cadastro</h2>
<label for="nome">Nome:</label>
<input type="text" id="nome" name="nome" required>
<label for="email">Email:</label>
<input type="email" id="email" name="email" required>
<label for="senha">Senha:</label>
<input type="password" id="senha" name="senha" required>
<button type="submit">Cadastrar</button>
</form>
<div id="cartaoCadastro" class="card"></div>
<script src="main.js"></script>
</body>
</html>
Arquivo CSS:
body {
font-family: Arial, sans-serif;
background-color: #f4f4f4;
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
margin: 0;
}
.container {
background-color: white;
padding: 20px;
border-radius: 8px;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
}
form {
display: flex;
flex-direction: column;
}
label {
margin: 10px 0 5px;
}
input {
padding: 8px;
margin-bottom: 10px;
border: 1px solid #ccc;
border-radius: 4px;
}
button {
padding: 10px;
background-color: #5cb85c;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
}
button:hover {
background-color: #4cae4c;
}
.card {
margin-top: 20px;
padding: 10px;
border: 1px solid #ddd;
border-radius: 4px;
background-color: #f9f9f9;
display: none;
background-color: #e9f7f9;
transition: all 0.3s ease;
}
Espero que por meio desse desafio seja possível aprender ainda mais sobre os eventos do DOM.
Referências
Caso queira aprender mais sobre os eventos JavaScript e outras formas de manipular o DOM, recomendo os materiais abaixo: