📚 Pré-requisitos Teóricos: este projeto aplica conceitos ensinados no Módulo 05: JavaScript Fundamentos e DOM. Recomendado revisar antes de iniciar a execução.
v1.0 — Implementação profunda dos princípios internos do Vue 3 e React: Proxy traps, rastreamento de dependências com WeakMap, árvore de Virtual DOM e algoritmo de reconciliação (diffing).
Trilha de Especialização Pedagógica — Série Front-End Moderno (Projeto 4 de 10)
- Design System & Tokens
- Manipulação Avançada de DOM & Storage
- SPA com Vanilla Router & History API
- Mini-Framework Reativo (este): Proxies JS, Dependency Tracking e Virtual DOM
🎓 Nível Profissional Simulado: Arquiteto de Software Frontend / Desenvolvedor Sênior. Desenvolvedores seniores não apenas usam bibliotecas: entendem como elas funcionam por baixo dos panos. Construir um motor reativo completo com a Proxy API e uma árvore de nós virtuais com algoritmo de diffing atômico consolida a maestria sobre os custos computacionais de renderização na web.
O projeto adota a convenção padronizada de subpastas por camada e tecnologia <camada>-<tecnologia>:
catalogo_projetos/js_04_mini_reactive_framework/
├── web-vanilla/ # Motor reativo nativo
│ └── reactive.js # Classes Dep, reactive(), watchEffect() e renderizador VNode
├── assets/ # Galeria de diagramas vetoriais SVG autorais
└── README.md # Explicação dos algoritmos e benchmarks
reactive(state) para que qualquer alteração em suas propriedades notifique automaticamente os observadores.watchEffect(fn) para que ela reexecute automaticamente sempre que qualquer propriedade acessada sofrer mutação.h(tag, props, children) para representar a interface em memória antes de tocar no DOM real.WeakMap) para prevenir vazamentos de memória (memory leaks) quando objetos forem destruídos.reactive() deve utilizar new Proxy() interceptando as operações get (para registrar dependências com dep.depend()) e set (para notificar alterações com dep.notify()).WeakMap<Target, Map<Key, Set<Effect>>>.set deve utilizar Reflect.set() e disparar notificações apenas quando o novo valor for diferente do anterior (oldValue !== newValue).watchEffect(effect) deve associar a função ativa na variável global activeEffect antes de sua primeira execução para captura das dependências.onClick).WeakMap.Set, impedindo que o mesmo efeito seja duplicado na lista de assinantes.flowchart LR
subgraph Atores
Dev["💻 Engenheiro de Software"]
Engine["⚙️ Motor Reativo (Proxies)"]
end
subgraph "Mini-Framework Reativo"
UC01["UC01: Declarar Estado Reativo com reactive()"]
UC02["UC02: Registrar Efeito com watchEffect()"]
UC03["UC03: Rastrear Dependências via Proxy GET"]
UC04["UC04: Disparar Reconciliação via Proxy SET"]
UC05["UC05: Aplicar Patch no DOM Real"]
end
Dev --> UC01
Dev --> UC02
UC01 --> UC03
Dev --> UC04
UC04 --> Engine
Engine --> UC05
| ID Requisito | História de Usuário | Caso de Uso | Módulo / Função (web-vanilla) |
Mecanismo JavaScript | Status |
|---|---|---|---|---|---|
| RF-RF01 | US-RF01 | UC01 / UC03 | reactive(raw) |
new Proxy() & Reflect |
✅ Coberto |
| RF-RF02 | US-RF05 | UC03 | getDep(target, key) |
WeakMap e Map |
✅ Coberto |
| RF-RF03 | US-RF01 | UC04 | Proxy handler.set() |
Reflect.set() |
✅ Coberto |
| RF-RF04 | US-RF02 | UC02 | watchEffect(effect) |
activeEffect & Set.forEach |
✅ Coberto |
| RF-RF05 | US-RF03 / US-RF04 | UC05 | h(tag, props, children) |
Árvore VNode & appendChild |
✅ Coberto |
ℹ️ O trecho de código que ficava aqui não correspondia ao código do projeto e foi retirado. Consulte os arquivos em
web-vanilla.
cd catalogo_projetos/js_04_mini_reactive_framework
node -e "
const { reactive, watchEffect } = require('./web-vanilla/reactive.js');
const s = reactive({ valor: 10 });
watchEffect(() => console.log('Valor:', s.valor));
s.valor = 42;
"
| Checkpoint | Procedimento de Verificação | Critério de Aceite | Status |
|---|---|---|---|
| CP-01 | Executar teste de criação de Proxy via reactive(). |
Objeto encapsulado e operações de leitura preservadas via Reflect.get(). |
PASS ✅ |
| CP-02 | Invocar watchEffect() com função dependente de duas propriedades. |
Ambas as chaves registradas no targetMap correspondente. |
PASS ✅ |
| CP-03 | Modificar a primeira propriedade do estado. | Efeito reexecutado imediatamente com o novo valor refletido. | PASS ✅ |
| CP-04 | Modificar a segunda propriedade do estado. | Efeito reexecutado e propriedades independentes mantêm integridade. | PASS ✅ |
| CP-05 | Atribuir o mesmo valor atual à propriedade (state.prop = state.prop). |
Efeito ignorado sem disparos redundantes de notificação. | PASS ✅ |