- Entenda a estrutura da árvore DOM e seus nós.
- Aprenda a navegar e manipular elementos de forma eficiente.
- Descubra boas práticas para otimizar a performance no DOM.
O que é a Árvore DOM?
A árvore DOM representa a estrutura hierárquica de documentos HTML e XML, sendo acessada através do JavaScript. Cada nó na árvore corresponde a elementos, atributos ou até mesmo texto, formando uma estrutura que tem como raiz o objeto document. Os nós pais se conectam aos filhos por meio de propriedades como parentNode, childNodes e firstChild. Dessa forma, desenvolvedores podem utilizar métodos nativos para percorrer essa árvore sem depender de bibliotecas externas.
Estrutura Hierárquica e Tipos de Nós
O DOM classifica os nós em quatro tipos principais: Element, Text, Comment e Document. Os nós de elemento armazenam tags como div ou p, enquanto os nós de texto contêm o conteúdo textual. A propriedade nodeType retorna valores numéricos, onde 1 representa elementos e 3 representa texto. Além disso, a propriedade childNodes inclui todos os descendentes diretos, incluindo espaços em branco como nós de texto. Para ignorar nós vazios, recomenda-se usar children, que retorna apenas nós de elementos.
Exemplo prático:
const container = document.getElementById('main');
console.log(container.children.length); // número de elementos filhos
console.log(container.childNodes.length); // inclui nós de texto
Navegação Eficiente pela Árvore
Para otimizar buscas, métodos de seleção são fundamentais. O método getElementById localiza elementos por identificador único em tempo constante. Por outro lado, querySelector e querySelectorAll aceitam seletores CSS complexos, retornando o primeiro ou todos os matches, respectivamente. O método closest() permite subir na árvore até encontrar um ancestral correspondente.
As propriedades de navegação incluem:
parentElement: retorna o pai imediato como Element.nextSiblingepreviousSibling: acessam irmãos adjacentes.firstElementChildelastElementChild: retornam o primeiro e o último filho Element.
Loops recursivos são úteis para percorrer subárvores profundas:
function traverse(node) {
if (node.nodeType === 1) {
console.log(node.tagName);
Array.from(node.children).forEach(traverse);
}
}
traverse(document.body);
Manipulação de Elementos
A criação de novos elementos é feita através de createElement e createTextNode. O método appendChild insere um nó no final, enquanto insertBefore posiciona um nó antes de uma referência específica. O método replaceChild substitui nós existentes, e a remoção pode ser feita com removeChild ou o método moderno remove().
Para modificar atributos, você pode usar:
const img = document.createElement('img');
img.setAttribute('src', 'foto.jpg');
img.src = 'nova.jpg'; // atalho direto
img.classList.add('ativo');
img.style.color = 'red';
Event listeners podem ser integrados a elementos manipulados:
button.addEventListener('click', () => {
const novo = document.createElement('p');
novo.textContent = 'Adicionado dinamicamente';
container.appendChild(novo);
});
Atualização de Conteúdo e Estilos
O uso de innerHTML permite a inserção de markup, mas é necessário ter cuidado para evitar vulnerabilidades como XSS. Em contrapartida, textContent altera apenas o texto, sendo uma opção mais segura e rápida. A propriedade dataset possibilita o acesso a atributos data-* como propriedades camelCase.
Para manipular classes e estilos, métodos como classList.toggle e style.cssText são bastante utilizados. Além disso, media queries dinâmicas podem ser combinadas com matchMedia para criar layouts responsivos.
Exemplos Avançados de Navegação e Manipulação
A árvore de formulários permite a validação em tempo real:
const form = document.querySelector('form');
form.addEventListener('submit', e => {
e.preventDefault();
const inputs = form.querySelectorAll('input[required]');
inputs.forEach(input => {
if (!input.value) input.classList.add('erro');
});
});
Fragmentos de documento podem acelerar inserções múltiplas:
const fragment = document.createDocumentFragment();
for (let i = 0; i < 100; i++) {
const li = document.createElement('li');
li.textContent = `Item ${i}`;
fragment.appendChild(li);
}
lista.appendChild(fragment);
Boas Práticas de Performance
Para garantir uma boa performance, evite loops pesados no DOM e armazene referências em variáveis. O uso de requestAnimationFrame é recomendado para animações. Além disso, a delegação de eventos em elementos ancestrais reduz o número de listeners. Ferramentas como Lighthouse são úteis para identificar gargalos de reflow e repaint.
Propriedades como offsetWidth podem forçar o recálculo de layout, portanto, agrupe leituras e gravações separadamente. O MutationObserver é uma ferramenta eficaz para monitorar mudanças sem a necessidade de polling constante.
Por fim, o código modulariza funções de navegação e manipulação em classes reutilizáveis, facilitando testes unitários com Jest e jsdom.
Perguntas Frequentes
O que é a árvore DOM?
A árvore DOM é uma representação em forma de árvore da estrutura de documentos HTML e XML, permitindo que os desenvolvedores acessem e manipulem elementos através do JavaScript.
Como posso navegar pela árvore DOM?
Você pode navegar pela árvore DOM utilizando métodos como getElementById, querySelector e propriedades como parentNode e childNodes.
Quais são as melhores práticas para manipulação de elementos no DOM?
As melhores práticas incluem evitar loops pesados, usar requestAnimationFrame para animações, e aplicar delegação de eventos para reduzir o número de listeners.
Como posso garantir a segurança ao usar innerHTML?
Para garantir a segurança ao usar innerHTML, é importante validar e sanitizar qualquer entrada de usuário para evitar vulnerabilidades como XSS.