Back

Reatividade Sem um Framework: O Que o JavaScript Nativo Pode Fazer Hoje

Reatividade Sem um Framework: O Que o JavaScript Nativo Pode Fazer Hoje

Você quer comportamento reativo na UI—mudanças de estado que atualizam automaticamente o DOM—mas não quer enviar 40KB de código de framework para um widget simples. Boas notícias: a reatividade em JavaScript vanilla é totalmente viável com APIs que estão estáveis nos navegadores há anos.

Este artigo cobre as ferramentas nativas disponíveis no final de 2025 para construir UIs reativas: estado reativo baseado em Proxy, EventTarget e CustomEvent para pub/sub, e observadores do navegador para reações conscientes do DOM. Você aprenderá o que funciona hoje, o que está por vir e onde esses padrões se mapeiam aos internos dos frameworks.

Pontos-Chave

  • Objetos Proxy interceptam mudanças de propriedades e permitem atualizações automáticas do DOM sem dependências de frameworks
  • EventTarget e CustomEvent fornecem uma camada nativa de pub/sub para comunicação desacoplada entre componentes
  • Observadores do navegador (MutationObserver, IntersectionObserver, ResizeObserver) lidam com reatividade do DOM e layout
  • A proposta TC39 Signals pode padronizar primitivas de reatividade, mas os padrões atuais de Proxy + EventTarget alcançam resultados similares hoje

O Que Reatividade Realmente Significa

Reatividade é um loop simples: mudanças de estado disparam atualizações na UI. Frameworks automatizam isso com DOMs virtuais, compiladores ou rastreamento de dependências refinado. Mas a mecânica subjacente depende de recursos JavaScript que você pode usar diretamente.

O padrão central:

  1. Armazenar estado em uma estrutura rastreável
  2. Notificar assinantes quando o estado muda
  3. Atualizar apenas o DOM relevante

APIs nativas do navegador lidam com cada etapa sem dependências externas.

Estado Reativo Baseado em Proxy

O objeto Proxy intercepta acesso e atribuição de propriedades. Combinado com Reflect, forma a fundação do estado reativo baseado em proxy.

function createReactiveStore(initial, onChange) {
  return new Proxy(initial, {
    set(target, prop, value) {
      const result = Reflect.set(target, prop, value)
      onChange(prop, value)
      return result
    }
  })
}

const state = createReactiveStore({ count: 0 }, (prop, value) => {
  document.getElementById('count').textContent = value
})

state.count = 5 // DOM atualiza automaticamente

Este padrão parece “signal-like”—você escreve no estado e os efeitos são executados. O sistema de reatividade do Vue 3 usa Proxy internamente exatamente por essa razão.

Limitação: As armadilhas do Proxy disparam apenas em mutações aplicadas ao próprio objeto proxiado. Se objetos aninhados ou arrays não forem também envolvidos em seus próprios proxies, mudanças dentro deles (como array.push()) não serão rastreadas. Muitos desenvolvedores usam atualizações imutáveis (por exemplo, state.items = [...state.items, newItem]) para garantir que as atualizações sejam disparadas.

EventTarget e CustomEvent como Camada de Pub/Sub

Para comunicação desacoplada entre componentes, EventTarget fornece um mecanismo nativo de pub/sub. Qualquer objeto pode se tornar um emissor de eventos.

const bus = new EventTarget()

// Assinar
bus.addEventListener('state-change', (e) => {
  console.log('Novo valor:', e.detail)
})

// Publicar
bus.dispatchEvent(new CustomEvent('state-change', { 
  detail: { count: 10 } 
}))

Este padrão potencializa UI reativa com APIs nativas do navegador. Componentes assinam eventos, reagem a mudanças e permanecem desacoplados. Diferente de implementações customizadas de pub/sub, EventTarget se integra com as DevTools do navegador e segue semânticas de eventos padrão.

Observadores do Navegador para Reatividade do DOM

Quando você precisa reagir a mudanças no DOM ou layout—não apenas no estado—os observadores do navegador preenchem a lacuna.

MutationObserver observa modificações no DOM:

const observer = new MutationObserver((mutations) => {
  mutations.forEach(m => console.log('DOM mudou:', m))
})
observer.observe(document.body, { childList: true, subtree: true })

IntersectionObserver rastreia visibilidade de elementos—útil para lazy loading ou analytics.

ResizeObserver responde a mudanças no tamanho de elementos sem polling.

Essas APIs são estáveis há muito tempo e são seguras para produção. Elas complementam a reatividade orientada a estado ao lidar com casos onde fatores externos modificam o DOM.

A Proposta TC39 Signals: O Que Está Por Vir

Há um interesse crescente em padronizar primitivas de reatividade. A proposta TC39 Signals visa definir um modelo comum que os frameworks possam compartilhar.

Importante: A partir de 2025, isso ainda é uma proposta—não um recurso JavaScript implementado. Frameworks como Solid, Angular e Preact adotaram padrões signal-like, influenciando o design da proposta. Mas você não pode usar “signals nativos” nos navegadores hoje.

Os padrões Proxy + EventTarget acima alcançam objetivos similares. Se signals forem padronizados, a migração deve ser direta, já que o modelo mental se alinha.

Escolhendo o Padrão Certo

PadrãoMelhor ParaTrade-off
ProxyEstado local de componenteRastreia apenas mudanças no objeto proxiado, a menos que valores aninhados também sejam proxiados
EventTargetMensagens entre componentesConexão manual
MutationObserverReagir a mudanças externas no DOMOverhead de performance

Para aplicações pequenas e widgets, combinar estado baseado em Proxy com EventTarget cobre a maioria das necessidades de UI reativa sem overhead de framework.

Conclusão

Reatividade sem um framework é prática hoje. Proxy lida com rastreamento de estado, EventTarget fornece pub/sub, e observadores do navegador reagem a mudanças no DOM. Essas APIs são estáveis, bem documentadas e se compõem em um núcleo reativo leve.

Você não precisa de um framework para obter reatividade refinada. Você precisa entender as primitivas sobre as quais os frameworks são construídos—e agora você entende.

Perguntas Frequentes

As armadilhas do Proxy disparam apenas na atribuição direta de propriedades ao objeto proxiado. Para objetos aninhados, você precisa envolver recursivamente cada objeto aninhado em seu próprio Proxy, ou substituir toda a estrutura aninhada ao fazer mudanças. A maioria dos desenvolvedores opta por padrões de atualização imutável como spreading para criar novas referências.

EventTarget é uma API nativa do navegador que se integra com as DevTools e segue semânticas de dispatch padrão. Bubbling e capturing completos aplicam-se apenas quando o alvo do evento faz parte da árvore DOM. Bibliotecas customizadas podem oferecer recursos adicionais como listeners wildcard ou assinaturas únicas, mas EventTarget não requer dependências e funciona consistentemente em todos os navegadores modernos.

Use MutationObserver quando precisar reagir a mudanças no DOM feitas por código externo, scripts de terceiros ou extensões do navegador. Proxy rastreia mudanças de estado JavaScript que você controla. MutationObserver observa a árvore DOM real independentemente do que causou a mudança. Eles servem propósitos diferentes e frequentemente trabalham juntos.

A proposta Signals visa padronizar primitivas de reatividade que os frameworks podem compartilhar, não substituir APIs existentes. Proxy e EventTarget permanecerão abordagens válidas. Se Signals forem implementados, provavelmente complementarão esses padrões fornecendo uma interface padrão para rastreamento de dependências refinado entre diferentes bibliotecas.

Complete picture for complete understanding

Capture every clue your frontend is leaving so you can instantly get to the root cause of any issue with OpenReplay — the open-source session replay tool for developers. Self-host it in minutes, and have complete control over your customer data.

Check our GitHub repo and join the thousands of developers in our community.

OpenReplay