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 components com estado
  • Para integração com bibliotecas externas (como gráficos), use useRef apenas 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 que querySelector('#id')
  • getElementsByClassName() é mais rápido que querySelectorAll('.class') para coleções grandes
  • Use querySelectorAll quando precisar de seletores complexos ou NodeList com forEach

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