4 F4. Frameworks: el mismo componente en cuatro sabores
React, Vue, Angular y Svelte resolviendo el mismo problema
El mismo componente — un contador con un botón — escrito en JS vanilla, React, Vue, Angular y Svelte. Verás que el concepto (estado → UI) es idéntico y solo cambia la sintaxis: elegir framework es elegir dialecto, no religión.
4.1 El problema
“¿Qué framework aprendo?” es la pregunta que paraliza a todo el que empieza. La respuesta honesta: el concepto es uno — componentes con estado que repintan la UI. Los frameworks son cuatro dialectos de esa idea. Verlos lado a lado resolviendo exactamente lo mismo es la forma más rápida de entenderlos todos.
Un framework es un esqueleto de aplicación ya decidido: te da la estructura (rutas, validación, errores) y tú llenas la lógica. Diferencia con librería: la librería la llamas tú; el framework te llama a ti.
El estado es todo lo que el programa recuerda: las variables, la sesión, lo que muestra la UI. Stateless (sin estado) = el servidor no recuerda nada entre requests — cada request trae todo lo necesario.
4.2 Cómo lo resuelve un equipo
Un equipo no elige “el mejor” — elige por contexto:
- ¿Qué usa ya la empresa/equipo? (la razón #1 en la vida real)
- ¿Cuánta estructura quieres impuesta? (Angular la impone toda; React te deja decidir)
- ¿Tamaño del ecosistema y contratación? (React gana por goleada)
4.3 Conceptos nuevos
- U Componente: una pieza de UI con su estado y su vista — botón, tarjeta, página entera.
- U Reactividad: estado cambia → UI se actualiza sola. Cada framework la implementa distinto.
- U Vite + dev server: la herramienta que sirve tu app en desarrollo (
npm run dev).
Un paquete es una librería empaquetada lista para instalar. El package manager (npm, pip, go mod) las descarga, resuelve versiones compatibles y las registra en package.json / pyproject.toml / go.mod.
- U JSX / templates / SFC: cómo cada framework escribe “HTML con lógica dentro”.
4.4 Implementación: el contador, cinco formas
<div id="app"></div>
<script>
let count = 0; // estado
function render() { // UI = f(state), a mano
document.getElementById("app").innerHTML =
`<p>Count: ${count}</p><button id="b">+1</button>`;
document.getElementById("b").onclick = () => { count++; render(); };
}
render();
</script>Ya conoces el patrón del Cap. F3: mutas estado → llamas render. Todo lo demás es esto mismo con mejor ergonomía.
import { useState } from "react";
export default function Counter() {
const [count, setCount] = useState(0); // estado declarativo
return (
<div> {/* UI = f(state) */}
<p>Count: {count}</p>
<button onClick={() => setCount(count + 1)}>+1</button>
</div>
);
}useState devuelve [valor, setter]: llamar setCount cambia el estado y React re-renderiza solo — no escribes render().
<script setup>
import { ref } from "vue";
const count = ref(0); // estado reactivo
</script>
<template>
<p>Count: {{ count }}</p>
<button @click="count++">+1</button>
</template>
ref hace el dato reactivo: count++ actualiza el estado y el template se repinta solo — ni setCount ni render.
import { Component } from "@angular/core";
@Component({
selector: "app-counter",
template: `
<p>Count: {{ count }}</p>
<button (click)="count = count + 1">+1</button>
`,
})
export class CounterComponent {
count = 0; // el estado es un campo de la clase
}Angular organiza en clases + decoradores: el template reacciona a cambios del campo. Más estructura impuesta, más “framework completo”.
<script>
let count = 0; // variable normal — Svelte la hace reactiva al compilar
</script>
<p>Count: {count}</p>
<button on:click={() => count++}>+1</button>
Svelte es el más “mágico”: escribes JS casi normal y el compilador genera el código reactivo — el que menos boilerplate tiene.
4.5 ¿Por qué cada framework lo hace así?
Lo único que necesitas llevarte: los cinco hacen estado → UI. La diferencia real es cuánto decides tú vs cuánto decide el framework: React y Svelte te dan un mecanismo; Vue un sistema; Angular una arquitectura completa.
- React: re-ejecuta la función del componente y compara el resultado (virtual DOM) — explícito, predecible.
- Vue:
refenvuelve el dato y rastrea qué lo usa — reactividad automática por proxys. - Angular: detección de cambios sobre la clase + signals modernos — el más estructurado (inyección de dependencias nativa, como el backend de NestJS).
- Svelte: el compilador detecta qué variables usa el template y genera updates quirúrgicos del DOM — sin virtual DOM, más rápido y simple.
Muéstrame el MISMO componente (un contador con botón que incrementa) en
React, Vue, Angular y Svelte. Para cada uno: el código mínimo completo,
qué línea declara el estado, y qué línea hace que la UI se actualice.
Después compáralos en una tabla: sintaxis de estado, cómo se re-renderiza,
y qué tanto decide el framework por mí.
4.6 Herramientas: cómo arranca un proyecto frontend
Todos comparten el mismo ritual (idéntico al del backend del Cap. 2):
npm create vite@latest my-app -- --template react # o vue / svelte / vanilla
cd my-app && npm install
npm run dev # → http://localhost:5173 con hot reloadVite es el dev server estándar hoy: sirve tus archivos, compila JSX/TS al vuelo y recarga al guardar. El npm run dev del frontend es el gemelo del uvicorn --reload del backend.
4.7 Errores comunes
- “Aprender React” sin entender estado: si no entiendes
estado → UIdel Cap. F3, los hooks se sienten mágicos y frágiles. - Mutar el estado directamente en React:
count++no repinta — hay que llamarsetCount. En Vue/Svelte sí se muta. - Peleas de frameworks: el mejor framework es el del equipo que te contrata — el concepto transferible es lo que importa.
4.8 Buenas prácticas
- Aprende UNO bien, lee los demás: con React sólido, Vue/Svelte se aprenden en días — el concepto es el mismo.
- Componentes pequeños: un componente = una pieza de UI; si crece, se divide.
- Estado lo más cerca posible de quien lo usa — el global es para lo que de verdad comparten muchos.
4.9 Ejercicio
npm create vite@latest counter -- --template react, correnpm run devy cambia el texto del botón a “incrementar”.- Agrega un segundo botón “-1” al contador.
4.10 Mini reto
Explica con tus palabras por qué en React escribes setCount(count + 1) pero en Vue/Svelte basta count++. ¿Qué está haciendo cada framework por debajo?
Ejercicio 2.
<button onClick={() => setCount(count - 1)}>-1</button>Mini reto. React necesita el setter porque re-ejecuta el componente solo cuando el estado cambia a través de su API — count++ mutaría la variable sin avisarle a React. Vue/Svelte interceptan la asignación (proxy/compilador) y saben que el dato cambió solos. Misma reactividad, distinto mecanismo de “aviso”.
4.11 Vocabulario técnico del capítulo
Una variable es una caja con nombre donde guardas un valor: let total = 42 guarda el 42 bajo el nombre total. Puedes leerla y cambiarla después (total = 50). const = caja que no se puede reemplazar.
Una función es una receta reutilizable: recibe ingredientes (parámetros), hace pasos y devuelve un plato (return). La escribes una vez y la llamas mil veces: add(2, 3) → 5.
Una clase es el molde de un objeto: define qué datos y qué métodos tiene. class Task es el molde; new Task() es una instancia concreta. Go no tiene clases — usa struct + métodos sueltos.
return hace dos cosas a la vez: devuelve el resultado Y termina la función — lo que esté debajo nunca corre. return task = “aquí está el plato, salgo de la cocina”.
Una traza sigue un request a través de todo el sistema: entró por el gateway → llamó auth → consultó la BD → tardó 340ms en la query. Cuando algo anda lento, la traza dice exactamente dónde.
Un módulo es un archivo de código que exporta cosas para que otros archivos las importen. Es la unidad de organización: en vez de un archivo gigante, el código vive en módulos con responsabilidad propia.
Una API (Application Programming Interface) es el menú de un programa: la lista de operaciones que otros programas pueden pedirle. Tu frontend no habla con la base de datos — le pide cosas a la API, y la API decide.
El DOM es la página como árbol de objetos vivos: HTML es el papel, el DOM es lo que JavaScript puede tocar. element.textContent = "hola" cambia el DOM y el navegador repinta — el HTML original no se entera.
Una dependencia es código de terceros que tu proyecto usa: npm install, pip install, go get las traen. Cada una es deuda — ahora funciona, pero hay que mantenerla, actualizarla y confiar en ella.
El dev server (Vite, npm run dev) sirve tu app mientras desarrollas y recarga el navegador al guardar — hot reload. No es el servidor de producción: es la mesa de trabajo.
Un compilador traduce código a otra forma: TypeScript → JavaScript (transpila), Go → binario (compila). Atrapa errores antes de ejecutar. tsc, esbuild, go build son compiladores.
localhost significa “esta misma máquina” — es la dirección que tu computadora usa para hablarse a sí misma. Cuando desarrollas, el “servidor” y el “cliente” viven en tu laptop: por eso todo es localhost:3000.
El CPU es el cerebro que ejecuta instrucciones; cada núcleo puede ejecutar una cosa a la vez (por eso importan la concurrencia y los procesos paralelos). “CPU-bound” = el límite es el cálculo, no la espera.
Un servidor es una computadora que espera peticiones y las responde 24/7. Físicamente no es nada mágico: es una máquina (a veces una VM alquilada) corriendo tu programa, con la diferencia de que está siempre encendida y conectada.
Un reverse proxy (nginx, ALB, Cloudflare) es el portero: recibe todo el tráfico en el 443, termina TLS y reparte a tu app interna. La app nunca mira a internet directamente — el proxy la protege.