DOM: árvore viva da interface
O navegador parseia HTML e constrói o DOM (Document Object Model). JavaScript lê e altera essa árvore em resposta a eventos — cliques, submits, timers, respostas de API. Este é o mecanismo por trás de dashboards, formulários dinâmicos e SPAs.
Seleção e cache de elementos
const form = document.querySelector('#filtro-relatorio');
const tbody = document.querySelector('#tabela-corpo');
const feedback = document.querySelector('#feedback');
Query repetido em loop custa performance; selecione uma vez fora do loop ou use event delegation.
Eventos e preventDefault
form.addEventListener('submit', (event) => {
event.preventDefault();
const dados = new FormData(form);
const termo = String(dados.get('busca') || '').trim().toLowerCase();
filtrarLinhas(tbody, termo);
feedback.textContent = termo ? `Filtrando: ${termo}` : 'Exibindo todos';
});
Padrão state + render
const state = {
contador: 0,
limite: 10
};
function render() {
document.querySelector('#valor').textContent = state.contador;
document.querySelector('#btn-inc').disabled = state.contador >= state.limite;
}
document.querySelector('#btn-inc').addEventListener('click', () => {
if (state.contador < state.limite) {
state.contador += 1;
render();
}
});
render();
Estado canônico vive em objeto; DOM é projeção. Frameworks (React, Vue) industrializam esse padrão — entender manualmente primeiro evita “magia” opaca depois.
Event delegation
document.querySelector('#lista-tarefas').addEventListener('click', (e) => {
const btn = e.target.closest('[data-action="concluir"]');
if (!btn) return;
btn.closest('li')?.classList.toggle('concluida');
});
Fetch e renderização assíncrona
async function carregarIndicadores() {
const alvo = document.querySelector('#indicadores');
alvo.textContent = 'Carregando...';
try {
const res = await fetch('/api/indicadores');
if (!res.ok) throw new Error(`HTTP ${res.status}`);
const dados = await res.json();
alvo.innerHTML = dados.map(d =>
`<div class="card"><strong>${d.nome}</strong>: ${d.valor}</div>`
).join('');
} catch (erro) {
alvo.textContent = `Erro: ${erro.message}`;
}
}
Debounce em buscas
function debounce(fn, ms = 300) {
let timer;
return (...args) => {
clearTimeout(timer);
timer = setTimeout(() => fn(...args), ms);
};
}
const buscar = debounce((termo) => filtrarLinhas(tbody, termo), 300);
input.addEventListener('input', (e) => buscar(e.target.value));
Ciclo de vida da página e ordem de execução
HTML parseia de cima para baixo. Scripts sem defer ou async bloqueiam renderização. Com defer, o script executa após DOM pronto — padrão recomendado para app.js no final do body ou no head com defer.
Atualizações dinâmicas e acessibilidade
Ao injetar conteúdo com innerHTML, leitores de tela podem não anunciar mudança. Para feedback importante (erro de formulário, resultado de busca), use aria-live="polite" em região dedicada:
<div id="feedback" role="status" aria-live="polite"></div>
Atualize textContent dessa região em vez de só mudar cor de borda — usuários de tecnologia assistiva dependem disso.
Segurança: innerHTML e dados externos
Nunca concatene HTML com strings vindas de usuário ou API sem sanitizar — risco de XSS. Para texto simples, use textContent. Para HTML confiável, considere bibliotecas como DOMPurify (como esta plataforma faz na importação Markdown).
Exercício: lista de tarefas completa
Implemente CRUD mínimo: adicionar tarefa, marcar concluída, remover, filtrar (todas/ativas/concluídas). Estado em objeto único; função render() sincroniza DOM. Persista em localStorage. Critério de pronto: recarregar página mantém lista; teclado consegue submeter formulário com Enter.
Ponte para frameworks
React, Vue e Svelte automatizam “state + render” e diff eficiente da árvore. Entender o padrão manual evita tratar framework como caixa preta: quando algo quebra, você ainda sabe que o problema é estado desincronizado ou listener duplicado.
Para aprofundar na web
Para entender melhor este tema, pesquise por:
- "DOM JavaScript MDN introdução" — árvore de nós e APIs principais
- "event delegation JavaScript explicado" — listeners em listas dinâmicas
- "preventDefault submit formulário" — controle de envio sem reload
- "fetch API MDN tutorial" — requisições HTTP no navegador
- "debounce input search JavaScript" — evitar chamadas excessivas ao digitar
Implemente filtro de lista sem framework — só DOM API — antes de aprender React.
Atividades
preventDefault no submit impede:
Ver resposta
Resposta correta: B) Reload da página
Cancela comportamento nativo do formulário.
Event delegation é útil quando:
Ver resposta
Resposta correta: B) Itens são adicionados dinamicamente
Listener no ancestral captura eventos de filhos presentes ou futuros.
Explique state vs DOM no padrão render().
Ver resposta
state guarda dados canônicos; render sincroniza UI. Mudanças passam por atualizar state e chamar render, evitando divergência entre lógica e tela.
0 comments