Seleção de Elementos no DOM
A base de qualquer manipulação do DOM é saber localizar os elementos certos. O JavaScript oferece vários métodos nativos, cada um com seu caso de uso específico. Os métodos mais modernos e eficientes são querySelector() e querySelectorAll(), que aceitam qualquer seletor CSS válido.
// Seleciona o primeiro elemento que corresponde ao seletor
const titulo = document.querySelector('h1');
const botao = document.querySelector('.btn-primary');
const campo = document.querySelector('#email');
// Seleciona todos os elementos que correspondem
const paragrafos = document.querySelectorAll('p');
const itens = document.querySelectorAll('[data-tipo="destaque"]');
// Retorna um NodeList - é possível iterar com forEach
paragrafos.forEach(paragrafo => {
console.log(paragrafo.textContent);
});
Para casos específicos, você ainda encontrará getElementById(), getElementsByClassName() e getElementsByTagName() em código legado. A diferença principal é que esses últimos retornam HTMLCollections (dinâmicas) enquanto querySelectorAll() retorna NodeLists (estáticas), o que é geralmente preferível para evitar comportamentos inesperados durante iterações.
Manipulação de Elementos
Modificando Conteúdo e Atributos
Após selecionar um elemento, você pode modificar seu conteúdo, classes e atributos. As propriedades textContent e innerHTML são as mais usadas, com a diferença crítica de que innerHTML interpreta tags HTML enquanto textContent trata tudo como texto puro.
const elemento = document.querySelector('.mensagem');
// Modificar conteúdo (seguro para texto)
elemento.textContent = 'Olá, usuário!';
// Modificar conteúdo com HTML (cuidado com XSS)
elemento.innerHTML = '<strong>Importante:</strong> Verifique seus dados.';
// Modificar atributos individuais
elemento.setAttribute('data-status', 'ativo');
elemento.id = 'msg-principal';
// Trabalhar com classes
elemento.classList.add('destaque');
elemento.classList.remove('oculto');
elemento.classList.toggle('selecionado');
// Verificar se possui uma classe
if (elemento.classList.contains('erro')) {
console.log('Há um erro neste elemento');
}
Criando e Removendo Elementos
Às vezes você precisa gerar novos elementos dinamicamente. O processo envolve criar o elemento, configurá-lo e inserir no DOM.
// Criar um novo elemento
const novoItem = document.createElement('li');
novoItem.textContent = 'Item adicionado dinamicamente';
novoItem.className = 'item-novo';
// Inserir ao final da lista
const lista = document.querySelector('ul');
lista.appendChild(novoItem);
// Inserir em posição específica
const primeiroItem = lista.querySelector('li');
lista.insertBefore(novoItem, primeiroItem);
// Remover elementos
novoItem.remove();
// Ou remover via parent
lista.removeChild(novoItem);
Modificando Estilos
Você pode alterar estilos diretamente via propriedade style, mas a melhor prática é trabalhar com classes CSS. Ainda assim, há situações onde estilos inline são necessários.
const caixa = document.querySelector('.caixa');
// Modificar estilos inline (use com moderação)
caixa.style.backgroundColor = '#3498db';
caixa.style.padding = '20px';
caixa.style.display = 'block';
// Preferível: trabalhar com classes
caixa.classList.add('ativo');
// Obter valor computado de um estilo
const corFundo = window.getComputedStyle(caixa).backgroundColor;
console.log(corFundo);
Traversal e Navegação no DOM
Percorrendo a Árvore DOM
Traversal significa navegar entre elementos relacionados: pais, filhos, irmãos. Isso é essencial quando você precisa acessar elementos de forma relativa em vez de absoluta.
const elemento = document.querySelector('.item');
// Acessar o elemento pai
const pai = elemento.parentElement;
console.log(pai.className);
// Acessar todos os filhos
const filhos = elemento.children; // HTMLCollection
elemento.childNodes; // inclui nós de texto
// Primeiro e último filho
const primeiro = elemento.firstElementChild;
const ultimo = elemento.lastElementChild;
// Elementos irmãos
const proximo = elemento.nextElementSibling;
const anterior = elemento.previousElementSibling;
// Navegar múltiplos níveis
const avô = elemento.parentElement.parentElement;
Buscas Relativas com querySelector
Uma técnica poderosa é usar querySelector de forma relativa, começando de um elemento específico em vez de sempre partir do document.
const formulario = document.querySelector('form');
// Buscar elementos dentro do formulário
const emailField = formulario.querySelector('input[name="email"]');
const todos_inputs = formulario.querySelectorAll('input');
// Verificar se um elemento contém outro
const campo = formulario.querySelector('[type="text"]');
if (formulario.contains(campo)) {
console.log('O campo está dentro do formulário');
}
// Encontrar o elemento pai mais próximo que corresponde a um seletor
const linha = campo.closest('tr'); // útil para tabelas
const card = campo.closest('.card');
O método closest() é extremamente valioso: ele sobe a árvore DOM procurando o primeiro ancestral que corresponde ao seletor. Isso elimina a necessidade de escrever loops manuais para navegação.
Boas Práticas e Performance
Acessar o DOM é operação custosa. Minimize queries desnecessárias armazenando referências em variáveis. Ao manipular múltiplos elementos, agrupe as mudanças para evitar reflows contínuos.
// ❌ Ineficiente: seleciona o mesmo elemento 3 vezes
document.querySelector('.box').textContent = 'Novo texto';
document.querySelector('.box').classList.add('ativo');
document.querySelector('.box').style.display = 'block';
// ✅ Eficiente: armazena a referência
const box = document.querySelector('.box');
box.textContent = 'Novo texto';
box.classList.add('ativo');
box.style.display = 'block';
// ✅ Para operações em lote, use DocumentFragment
const fragment = document.createDocumentFragment();
for (let i = 0; i < 1000; i++) {
const item = document.createElement('li');
item.textContent = `Item ${i}`;
fragment.appendChild(item);
}
// Insere todos de uma vez
document.querySelector('ul').appendChild(fragment);
Conclusão
Dominar o DOM é fundamental para qualquer desenvolvedora ou desenvolvedor JavaScript. Os três pilares aprendidos neste artigo são: (1) seleção eficiente com querySelector e querySelectorAll, que cobrem 95% dos casos reais; (2) manipulação segura de conteúdo, classes e atributos, sempre preferindo classes para estilos em vez de estilos inline; e (3) traversal inteligente usando parentElement, closest() e buscas relativas, que torna seu código mais flexível e resiliente a mudanças estruturais no HTML.
Com esses conhecimentos e as práticas de performance, você está pronto para construir interfaces dinâmicas e responsivas.