Capítulo 19
DOM e eventos
5 min de leitura 946 palavras 2 gravuras
Até o capítulo 18 o JavaScript falava com o console. Agora ele fala com a página da Casa da Restinga. O DOM (Document Object Model, modelo de objeto do documento) é a árvore que o navegador monta a partir do HTML. Um evento avisa que a pessoa clicou ou digitou. Esta é o capítulo 19 de 23.
O exemplo está em exemplos/19-dom-eventos/. Abra index.html. Há um quadrado, um campo de texto e uma fileira de botões. Tudo usa querySelector e addEventListener.
Trabalhe na cópia inicio da etapa. Leia e digite o código; mude uma coisa. Antes de recarregar, anote sua previsão. Depois confira com a referência completa. Se nada mudar, confira o arquivo salvo e o caminho aberto. Blocos adicionais do capítulo podem ser digitados no console; o exemplo completo mostra a aplicação daquela etapa.
O que você vai aprender
- Distinguir arquivo no disco, página no navegador e teste em
127.0.0.1. - Achar o primeiro nó com
querySelector. - Achar vários com
querySelectorAll. - Esperar clique com
addEventListenerem umbutton. - Copiar o que a pessoa digita (
keyup) e reagir achange. - Ouvir o pai dos botões (delegação) em vez de um ouvinte por botão.
Do arquivo à tela
Você escreve no editor. O navegador pede o HTML. Lê o arquivo, vê o <script src="script.js">, pede o JS, executa.
Nesta máquina o disco faz o papel de servidor. Abrir o arquivo (file://) e servir em http://127.0.0.1 são testes locais. Publicar na internet é outro passo. Não publique estes exercícios.
O script fica no fim do body. Assim as tags já existem quando o código procura por elas.
<!DOCTYPE html>
<html lang="pt-BR">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Balcão — Casa da Restinga</title>
<link rel="stylesheet" href="styles.css">
</head>
<body>
<main>
<h1>Balcão da Restinga</h1>
<div class="quadrado"></div>
<p>
<button type="button" class="aviso">Tocar sino</button>
</p>
<label for="pedido">Pedido</label>
<input id="pedido" class="pedido" type="text">
<p class="eco">Nada digitado ainda.</p>
<div class="fileira">
<button type="button">1</button>
<button type="button">2</button>
<button type="button">3</button>
<button type="button">4</button>
<button type="button">5</button>
</div>
<p class="mesa">Nenhuma mesa.</p>
</main>
<script src="script.js"></script>
</body>
</html>
Botão que só dispara ação é <button type="button">. Não use div clicável.
Pare e experimente. Abra o exemplo. Preveja o título “Balcão da Restinga”. Recarregue. Confira a aba.
Erro comum: script no head sem espera. querySelector devolve null e a página quebra.

document e querySelector
document é o objeto global da página. querySelector recebe um seletor CSS e devolve o primeiro elemento que combina.
const quadrado = document.querySelector(".quadrado");
quadrado.style.backgroundColor = "seagreen";
Mesmo que o CSS pinte o quadrado de outra cor, o JS manda depois e ganha nesta propriedade.
No CSS a propriedade é background-color (com hífen). No JS vira backgroundColor (camelCase). padding-right vira paddingRight.
Pare e experimente. Troque "seagreen" por "coral". Preveja o quadrado alaranjado. Recarregue. Confira.
Erro comum: querySelector("quadrado") sem o ponto. Isso procura uma tag <quadrado>, que não existe.
querySelectorAll
querySelectorAll devolve todos os que combinam, numa lista com length. Percorra com for.
const alvos = document.querySelectorAll(".js-alvo");
for (let i = 0; i < alvos.length; i += 1) {
alvos[i].textContent = "Atualizado no balcão";
}
textContent grava texto visível. Não interpreta HTML. Serve para status e rótulos.
Se ninguém combinar, querySelector devolve null. querySelectorAll devolve lista vazia, não null.
Pare e experimente. No HTML de estudo, ponha class="js-alvo" em dois p. Preveja dois textos iguais. Recarregue. Confira.
Erro comum: tratar querySelectorAll como um único nó e fazer alvos.textContent = …. A lista não tem textContent. Cada item tem.
Clique no button
Um evento é o aviso. O ouvinte (addEventListener) diz qual função roda.
const sino = document.querySelector(".aviso");
sino.addEventListener("click", function () {
window.alert("Pedido no balcão da Restinga.");
});
Dois parâmetros: o nome do evento ("click") e a função. Essa função é o callback: o navegador a chama de volta quando o clique acontece.
alert vem de window.alert. No navegador você pode omitir window. Use com parcimônia: a caixa trava a página até o OK.
A linha termina em }); porque fecha a função, fecha a chamada e termina o comando.
Pare e experimente. Troque o texto do alerta. Preveja a frase nova. Recarregue. Clique no botão. Confira.
Erro comum: escrever addEventListener("Click") com C maiúsculo. O nome é "click" em minúsculas.
Digitação: keyup e change
keyup dispara quando a tecla sobe. input.value é o que está no campo. Copie para um parágrafo.
const campo = document.querySelector(".pedido");
const eco = document.querySelector(".eco");
campo.addEventListener("keyup", function () {
eco.textContent = campo.value;
});
Use keyup (e não keydown) para não ficar uma letra atrasado: keydown ocorre antes do caractere entrar no campo.
change no mesmo espírito espera a pessoa sair do campo (Tab ou clique fora). Útil para aplicar uma cor só no fim.
const tinta = document.querySelector(".pedido");
tinta.addEventListener("change", function () {
document.querySelector(".quadrado").style.backgroundColor = tinta.value;
});
Digite navy e saia do campo. Cor inválida: o quadrado não muda.
Pare e experimente. Digite Café coado no pedido. Preveja o mesmo texto em .eco a cada letra. Recarregue se o ouvinte não ligou.
Erro comum: ouvir keydown e copiar value. A última tecla ainda não está no campo.

Um ouvinte na fileira
Vários botões, um pai. O clique sobe (bubbling) até o container. Você escuta o pai e pergunta quem foi o event.target.
const fileira = document.querySelector(".fileira");
const mesa = document.querySelector(".mesa");
fileira.addEventListener("click", function (evento) {
const botao = evento.target.closest("button");
if (!botao) {
return;
}
mesa.textContent = "Mesa " + botao.textContent.trim();
});
evento sempre chega; antes você o ignorava. target é a tag de origem. closest("button") garante que você pega o botão mesmo se o clique acertar um filho.
Isso se chama delegação. Um ouvinte só. A calculadora da próximo capítulo usa a mesma ideia.
Pare e experimente. Clique no 3. Preveja “Mesa 3”. Recarregue. Clique no 5. Confira.
Erro comum: ouvir o document inteiro e reagir a qualquer clique da página, inclusive no título. Ouça só .fileira.
Atividades
- Por que o
<script>fica no fim dobodyneste exemplo? querySelector(".quadrado")devolve o quê se houver dois elementos com essa classe?- Qual a diferença entre
keyupechangeno campo? - Na fileira, para que serve
evento.target?
Respostas comentadas
- Para o HTML já ter nascido. Se o script rodar antes,
querySelectorachanull. - Só o primeiro. Para os dois, use
querySelectorAll. keyupatualiza a cada tecla.changeespera a pessoa sair do campo.- É a tag onde o evento começou. Com
closest("button")você obtém o botão clicado.
MDN
- Document.querySelector
- Document.querySelectorAll
- EventTarget.addEventListener
- HTMLButtonElement
- Event.target
O arquivo completo
Referência do exemplo 19-dom-eventos, reproduzida aqui para que você possa conferir sem sair da página.
dom.js
const quadrado = document.querySelector(".quadrado");
quadrado.style.backgroundColor = "seagreen";
document.querySelector(".aviso").addEventListener("click", () => {
quadrado.style.backgroundColor = "coral";
});
const campo = document.querySelector(".pedido");
const eco = document.querySelector(".eco");
campo.addEventListener("keyup", () => {
eco.textContent = campo.value || "Nada digitado ainda.";
});
const fileira = document.querySelector(".fileira");
const mesa = document.querySelector(".mesa");
fileira.addEventListener("click", (evento) => {
const botao = evento.target.closest("button");
if (!botao) return;
mesa.textContent = "Mesa " + botao.textContent;
});