Manipulação do DOM: querySelector, eventos e innerHTML
Vamos aprender a selecionar elementos na página, reagir a eventos do usuário e atualizar o conteúdo HTML dinamicamente com JavaScript.
Introdução
Quando escrevemos JavaScript para o navegador, nosso “campo de trabalho” é o DOM (Document Object Model): uma representação em árvore do HTML da página.
Manipular o DOM significa selecionar elementos, ler e alterar conteúdo, estilos e atributos, além de reagir a interações do usuário (cliques, teclas, envio de formulário, etc.).
Ilustração da árvore DOM
O DOM (Document Object Model) representa a página HTML como uma árvore de nós,
em que cada elemento e cada texto viram objetos conectados hierarquicamente.
A estrutura acima é convertida pelo navegador em uma árvore de nós, começando em
Document, com o elemento html como raiz do documento.
Document
└── html
├── head
│ └── title
│ └── "Página exemplo"
└── body
├── h1
│ └── "Olá, DOM!"
└── p
└── "Um parágrafo de teste."
Cada elemento da marcação (html, head, body, h1, p, title) é um nó do tipo Element,
e os textos entre as tags são nós do tipo Text na árvore DOM.
Vamos focar em três ideias fundamentais: querySelector para selecionar, eventos para reagir e innerHTML para atualizar o conteúdo.
1. DOM e querySelector
Com JavaScript, podemos acessar esses objetos pelo objeto global document e alterar a página sem recarregar.
1.1 Selecionando elementos com querySelector
document.querySelector(seletor) retorna o primeiro elemento que combina com o seletor CSS informado.
O seletor é exatamente o mesmo que você usaria no CSS: #id, .classe, tag, combinações, etc.
// Seleciona o primeiro parágrafo da página
const primeiroParagrafo = document.querySelector("p");
// Seleciona o elemento com id "titulo"
const titulo = document.querySelector("#titulo");
// Seleciona o primeiro elemento com a classe "destaque"
const destaque = document.querySelector(".destaque");
Resumo: use # para id, . para classe e o nome da tag para elementos simples.
1.2 Selecionando vários elementos com querySelectorAll
Enquanto document.querySelector() devolve apenas o primeiro elemento que combina com o seletor,
document.querySelectorAll() retorna todos os elementos que combinam, em uma lista (NodeList).
// Seleciona todos os parágrafos da página
const paragrafos = document.querySelectorAll("p");
// Acessa o 3º parágrafo (índice 2)
const terceiroParagrafo = paragrafos[2];
// Altera o texto do 3º parágrafo
terceiroParagrafo.textContent = "Sou o terceiro parágrafo!";
Lembre que os índices começam em 0: o primeiro parágrafo é [0], o segundo é [1], o terceiro é [2] e assim por diante.
1.2.1 Exemplo: quarta ocorrência de uma classe
Também podemos buscar várias ocorrências de uma mesma classe e acessar uma posição específica da lista,
como a 4ª ocorrência de elementos com a classe .destaque.
// Seleciona todos os elementos com a classe "destaque"
const destaques = document.querySelectorAll(".destaque");
// Pega a 4ª ocorrência (índice 3)
const quartoDestaque = destaques[3];
// Adiciona uma borda para visualizar
quartoDestaque.style.border = "2px solid red";
1.2.2Combinação com seletores de CSS
Podemos combinar querySelectorAll com seletores de CSS, por exemplo,
para pegar o 3º parágrafo dentro de um container específico:
// Seleciona o container com id "conteudo"
const conteudo = document.querySelector("#conteudo");
// Dentro do container, pega todos os parágrafos
const paragrafosConteudo = conteudo.querySelectorAll("p");
// 3º parágrafo desse container
const terceiroNoConteudo = paragrafosConteudo[2];
Resumo: use querySelector() quando quiser apenas um elemento e
querySelectorAll() quando precisar de uma lista para acessar posições específicas (3º, 4º etc.).
1.3 querySelector dentro de outro elemento
Também podemos chamar querySelector em um elemento, não só em document, para procurar dentro dele.
// Seleciona a seção principal
const secao = document.querySelector("section");
// Dentro da seção, seleciona o primeiro <h2>
const subtitulo = secao.querySelector("h2");
1.4 Preview rápido: selecionando e destacando um elemento
Veja o exemplo abaixo: vamos buscar um parágrafo pelo id e mudar o estilo dele via JavaScript.
Podemos ouvir eventos no document inteiro, por exemplo para contar quantas teclas o usuário digitou.
let teclasDigitadas = 0;
const saida = document.querySelector("#saida-teclas");
const campoTeclas = document.querySelector("#campo-teclas");
// Aqui nós registramos um "ouvinte de eventos" no documento inteiro.
// "keyup" é disparado sempre que uma tecla é SOLTA.
// A função (evento) => { ... } será executada a cada vez que isso acontecer.
//campoTeclas.addEventListener("keyup", (evento) => { conta apenas no campo
document.addEventListener("keyup", (evento) => {
teclasDigitadas++;
saida.textContent = "Teclas digitadas: " + teclasDigitadas;
});
Preview – Contando teclas digitadas (keyup)
Digite qualquer coisa no campo abaixo e observe o contador:
Teclas digitadas: 0
3. innerHTML na prática
3.1 O que é innerHTML?
innerHTML é uma propriedade que representa o conteúdo HTML interno de um elemento.
Podemos ler esse conteúdo ou sobrescrevê-lo com uma nova string contendo HTML.
const caixa = document.querySelector("#caixa");
// Lendo o HTML interno
console.log(caixa.innerHTML);
// Substituindo o conteúdo
caixa.innerHTML = "<strong>Novo conteúdo</strong> gerado via JS!";
Se você só precisa trocar texto simples, prefira textContent. Use innerHTML quando realmente quiser inserir tags HTML (por exemplo, <strong>, <li>, <em>, etc.).
3.2 Exemplo: mensagem dinâmica
No exemplo abaixo, ao clicar no botão trocamos o conteúdo de uma <div> usando innerHTML.
Preview – innerHTML para atualizar mensagem
Clique no botão para alterar esta mensagem.
<div id="mensagem-dom">
Clique no botão para alterar esta mensagem.
</div>
<button id="btn-mudar-mensagem">Mudar mensagem</button>
<script>
const mensagem = document.querySelector("#mensagem-dom");
const btnMensagem = document.querySelector("#btn-mudar-mensagem");
btnMensagem.addEventListener("click", () => {
mensagem.innerHTML = "Mensagem <strong>atualizada</strong> com (...)";
});
</script>
3.3 Montando uma lista com innerHTML
Também podemos construir um HTML inteiro em uma string e atribuir de uma vez para montar uma lista dinamicamente.
const frutas = ["Maçã", "Banana", "Laranja"];
const lista = document.querySelector("#lista-frutas");
let html = "";
for (const fruta of frutas) {
html += "<li>" + fruta + "</li>";
}
lista.innerHTML = html;
Em aplicações maiores, é comum preferir document.createElement e appendChild para manipular nós de forma mais controlada, mas innerHTML é ótimo para exemplos simples e protótipos.
4. Mini-projeto: lista de tarefas com DOM
Agora vamos juntar querySelector, eventos e innerHTML em um mini “gerenciador” de tarefas simples.
4.1 Comportamento desejado
O usuário digita uma tarefa em um input.
Clica em “Adicionar” ou aperta Enter.
A tarefa aparece em uma lista abaixo.
Se o campo estiver vazio, exibimos uma mensagem de erro.
// 1. Selecionar elementos da página
const inputTarefa = document.querySelector("#tarefa-input");
const btnAdicionar = document.querySelector("#btn-adicionar-tarefa");
const listaTarefas = document.querySelector("#lista-tarefas");
const pErro = document.querySelector("#erro-tarefa");
// 2. Array para guardar as tarefas (estado da aplicação)
const tarefas = [];
// 3. Função para redesenhar a lista usando innerHTML
function atualizarLista() {
let html = "";
for (const tarefa of tarefas) {
html += "<li>" + tarefa + "</li>";
}
listaTarefas.innerHTML = html;
}
// 4. Função para adicionar uma nova tarefa
function adicionarTarefa() {
const texto = inputTarefa.value.trim();
if (texto === "") {
pErro.textContent = "Digite uma tarefa antes de adicionar.";
return;
}
pErro.textContent = ""; // limpa mensagem de erro
tarefas.push(texto);
inputTarefa.value = "";
atualizarLista();
}
// 5. Conectar eventos
btnAdicionar.addEventListener("click", adicionarTarefa);
// Permite adicionar com Enter
inputTarefa.addEventListener("keyup", (evento) => {
if (evento.key === "Enter") {
adicionarTarefa();
}
});
Para testar em um arquivo separado, crie um index.html simples e um tarefas.js com o código acima, da mesma forma que você já fez nas aulas anteriores.
Para memorizar!
1 – Alterando o tema da página
Crie dois botões: “Tema claro” e “Tema escuro”. Ao clicar em cada um, altere o backgroundColor do body e a cor do texto usando querySelector e eventos.
Use document.querySelector("body") para pegar o body.
No evento de clique dos botões, altere style.backgroundColor e style.color.
2 – Lista de compras
Baseando-se na lista de tarefas, crie uma lista de compras que mostre a quantidade de itens abaixo da lista.
Use um <span> para exibir o total de itens.
Atualize o texto do span sempre que adicionar um item, com textContent.
3 – Perguntas e respostas
Monte uma página com três perguntas de revisão. Ao clicar em um botão “Mostrar resposta”, mostre a resposta usando innerHTML em uma <div> escondida.
Comece com a <div> vazia.
No clique, use div.innerHTML = "Resposta: ...".
Roteiro de estudo para quem faltou
Revise a ideia de DOM e como o navegador transforma HTML em uma árvore de elementos.
Pratique querySelector e addEventListener com pequenos exemplos (botões, parágrafos, inputs).
Experimente trocar innerHTML e textContent e observe a diferença.
Implemente o mini-projeto da lista de tarefas e uma das atividades propostas.