DOM: selecionando elementos
1. Introdução à Seleção de Elementos no DOM
O DOM (Document Object Model) é a representação em árvore de um documento HTML, onde cada nó é um objeto que pode ser manipulado por JavaScript. Selecionar elementos é a primeira etapa para qualquer interação dinâmica: alterar conteúdo, estilos, ouvir eventos ou animar componentes. Sem seleção eficiente, não há manipulação.
Existem duas categorias principais: seleção única (retorna um único elemento) e seleção múltipla (retorna uma coleção). Os métodos modernos (querySelector, querySelectorAll) oferecem flexibilidade com sintaxe CSS, enquanto os métodos clássicos (getElementById, getElementsByClassName) são mais específicos e, em alguns casos, mais performáticos.
2. Métodos Clássicos de Seleção
getElementById()
Retorna o elemento com o ID especificado. É o método mais rápido para seleção única, pois IDs devem ser únicos no documento.
const header = document.getElementById('main-header');
console.log(header.textContent); // "Meu Site"
getElementsByClassName() e getElementsByTagName()
Ambos retornam uma HTMLCollection (coleção viva, que se atualiza automaticamente conforme o DOM muda).
const cards = document.getElementsByClassName('card');
console.log(cards.length); // 3
const paragraphs = document.getElementsByTagName('p');
for (let p of paragraphs) {
p.style.color = 'blue';
}
getElementsByName()
Seleciona elementos pelo atributo name, comum em formulários.
const radios = document.getElementsByName('opcao');
radios[0].checked = true;
3. Seletores Modernos com querySelector
querySelector()
Retorna o primeiro elemento que corresponde ao seletor CSS fornecido.
const firstButton = document.querySelector('.btn-primary');
const mainDiv = document.querySelector('#app > div.container');
querySelectorAll()
Retorna uma NodeList (estática, não atualiza automaticamente) com todos os elementos correspondentes.
const allItems = document.querySelectorAll('ul li.active');
allItems.forEach(item => item.classList.add('highlight'));
Sintaxe de seletores CSS
Você pode usar qualquer seletor CSS válido:
// Por atributo
const inputs = document.querySelectorAll('input[type="email"]');
// Combinadores
const nested = document.querySelector('div > p + span');
// Pseudo-classes
const oddRows = document.querySelectorAll('tr:nth-child(odd)');
4. Navegação entre Elementos no DOM
Após selecionar um elemento, você pode navegar pela árvore DOM usando propriedades de navegação.
Propriedades de elemento vs. nó
const section = document.querySelector('.content');
// Propriedades de elemento (ignoram nós de texto)
console.log(section.children); // HTMLCollection (apenas elementos)
console.log(section.parentElement); // elemento pai
console.log(section.nextElementSibling); // próximo irmão elemento
console.log(section.previousElementSibling); // irmão anterior elemento
// Propriedades de nó (incluem texto e comentários)
console.log(section.childNodes); // NodeList (inclui text nodes)
closest() e matches()
closest() sobe na árvore até encontrar um seletor correspondente. matches() verifica se o elemento atual corresponde a um seletor.
const btn = document.querySelector('.delete-btn');
const card = btn.closest('.card'); // encontra o card mais próximo
if (btn.matches('[data-action="delete"]')) {
console.log('Botão de deletar clicado');
}
5. Seleção em Contexto Node.js (jsdom)
Em Node.js, não há DOM nativo. Usamos jsdom para simular um ambiente de navegador.
Instalação e configuração
const { JSDOM } = require('jsdom');
const dom = new JSDOM(`
<!DOCTYPE html>
<div id="app">
<button class="btn">Clique</button>
</div>
`);
const document = dom.window.document;
const button = document.querySelector('.btn');
console.log(button.textContent); // "Clique"
Limitações
- Layout e estilos não são renderizados (sem CSSOM completo)
- Eventos funcionam, mas sem interação visual
- Performance inferior ao navegador real
// Boa prática: extrair apenas o necessário
const { document } = (new JSDOM(html)).window;
const links = document.querySelectorAll('a[href]');
6. Seleção de Elementos no React
No React, a abordagem declarativa geralmente elimina a necessidade de seleção direta. Mas quando necessário, use useRef.
useRef() para referenciar elementos
import React, { useRef, useEffect } from 'react';
function VideoPlayer() {
const videoRef = useRef(null);
useEffect(() => {
// Acesso direto ao elemento DOM após montagem
videoRef.current.play();
}, []);
return <video ref={videoRef} src="video.mp4" />;
}
Seleção indireta via estado
function Accordion() {
const [isOpen, setIsOpen] = React.useState(false);
// Em vez de selecionar o elemento, use estado
return (
<div>
<button onClick={() => setIsOpen(!isOpen)}>Toggle</button>
{isOpen && <div className="content">Conteúdo</div>}
</div>
);
}
Quando evitar seleção direta
- Para animações controladas por estado, prefira bibliotecas como
framer-motion - Para formulários, use
controlled componentscom estado - Para integração com bibliotecas externas (como gráficos), use
useRefapenas no elemento raiz
7. Performance e Boas Práticas
Custo de performance
// Ruim: consulta repetida
document.querySelector('.item').style.color = 'red';
document.querySelector('.item').style.fontSize = '16px';
// Bom: cache da seleção
const item = document.querySelector('.item');
item.style.color = 'red';
item.style.fontSize = '16px';
Métodos específicos vs. querySelectorAll
getElementById()é mais rápido quequerySelector('#id')getElementsByClassName()é mais rápido quequerySelectorAll('.class')para coleções grandes- Use
querySelectorAllquando precisar de seletores complexos ou NodeList comforEach
Tratamento de elementos não encontrados
const element = document.querySelector('.nao-existe');
if (element) {
// seguro para manipular
} else {
console.warn('Elemento não encontrado');
}
8. Casos de Uso Avançados
Seleção em Shadow DOM
const host = document.querySelector('#shadow-host');
const shadowRoot = host.shadowRoot;
const innerButton = shadowRoot.querySelector('.shadow-btn');
Combinação de seletores para filtros complexos
// Selecionar inputs visíveis e habilitados dentro de um formulário específico
const validInputs = document.querySelectorAll(
'#form-cadastro input:not([disabled]):not([type="hidden"])'
);
Depuração no console do navegador
// No console do navegador
$0 // último elemento inspecionado
$('.minha-classe') // querySelector
$$('div p') // querySelectorAll
Referências
- MDN Web Docs: Document.querySelector() — Documentação oficial com exemplos de uso do método moderno de seleção.
- MDN Web Docs: NodeList vs HTMLCollection — Explica as diferenças entre coleções vivas e estáticas no DOM.
- jsdom: Documentação oficial — Repositório e guia de uso do jsdom para simular DOM em Node.js.
- React: useRef Hook — Documentação oficial do React sobre referenciamento de elementos DOM.
- W3Schools: JavaScript HTML DOM Navigation — Tutorial prático sobre navegação entre elementos pai, filho e irmãos.
- CSS-Tricks: A Complete Guide to querySelector — Guia completo com exemplos avançados de seletores CSS no JavaScript.