¿Qué es Vue?
Ya sabes escribir HTML, darle estilo con CSS, hacer que una página reaccione con JavaScript y gestionar tu código con Git. Has construido cosas reales. Pero si te fijas en lo que hiciste con JavaScript, hay algo que se repite constantemente: seleccionar un elemento del DOM, cambiarle el contenido, escuchar un evento, volver a actualizar el DOM... Es un ciclo manual que se vuelve agotador cuando la interfaz crece.
Imagina el menú de Café Estelar con 30 productos, un buscador que filtra en tiempo real, un carrito de compras que se actualiza al instante y un formulario de pedido que valida cada campo mientras escribes. Hacerlo todo con querySelector y textContent es viable, pero vas a terminar con cientos de líneas de código repetitivo, frágil y difícil de mantener.
Vue existe para resolver exactamente este problema.
Un framework progresivo para interfaces
Vue es un framework progresivo para construir interfaces de usuario. Fue creado por Evan You en 2014 y es uno de los frameworks JavaScript más populares del mundo, junto con React y Angular.
¿Qué significa "progresivo"? Que puedes usarlo de muchas formas según lo que necesites:
- Puedes añadir Vue a una sola parte de una página HTML existente (como un formulario interactivo).
- Puedes construir una aplicación completa desde cero con Vue.
- Puedes ir añadiendo funcionalidades (enrutador, gestión de estado, testing) a medida que las necesites.
No te obliga a usar todo desde el principio. Empiezas con lo básico y creces según tu proyecto lo requiera. En este curso vamos a construir una aplicación completa, pero empezaremos con lo esencial.
¿Qué es una SPA (Single Page Application)?
Con lo que sabes hasta ahora, cada vez que el usuario hace clic en un enlace, el navegador pide una página nueva al servidor, la descarga entera y la renderiza desde cero. Eso funciona, pero tiene un problema: la experiencia es lenta y con parpadeos constantes.
Una SPA (Single Page Application) funciona diferente: el navegador carga una sola página HTML al principio, y a partir de ahí JavaScript se encarga de todo. Cuando el usuario navega a otra sección, JavaScript cambia el contenido dinámicamente sin recargar la página. El resultado es una experiencia fluida, como una aplicación nativa.
Piensa en aplicaciones como Gmail, Trello o Spotify Web. Cuando navegas dentro de ellas no ves la página recargarse — todo ocurre de forma instantánea. Eso es una SPA, y Vue es una de las herramientas más populares para construirlas.
Reactividad: la característica estrella
Aquí es donde Vue cambia las reglas del juego. Con JavaScript vanilla, si quieres que la interfaz refleje un cambio en los datos, tienes que hacerlo manualmente:
// ❌ JavaScript vanilla: actualización manual
let contador = 0;
function incrementar() {
contador++;
// Tienes que buscar el elemento y actualizarlo TÚ
document.querySelector("#contador").textContent = contador;
}
document.querySelector("#boton").addEventListener("click", incrementar);
Funciona, pero fíjate: tú eres responsable de mantener sincronizados los datos (contador) y la interfaz (#contador). Cuando tienes 5 datos es manejable. Cuando tienes 50, es una pesadilla.
Con Vue, la interfaz se actualiza automáticamente cuando los datos cambian:
// ✅ Vue: actualización automática (reactiva)
import { ref } from 'vue'
const contador = ref(0)
function incrementar() {
contador.value++
// ¡No necesitas tocar el DOM! Vue lo actualiza solo
}
Cambias el dato y la interfaz se actualiza sola. Eso es reactividad. Es como una hoja de cálculo: cuando cambias el valor de una celda, todas las fórmulas que dependen de ella se recalculan automáticamente. Vue hace lo mismo con tu interfaz.
Una nota sobre TypeScript
Vue tiene soporte nativo para TypeScript, y muchos proyectos profesionales lo utilizan. TypeScript añade tipado estático a JavaScript, lo que ayuda a detectar errores antes de ejecutar el código. Lo aprenderás más adelante en el curso. Por ahora usaremos JavaScript puro para que puedas aplicar directamente todo lo que aprendiste en la sección anterior sin introducir otra capa de complejidad.
Instalar Node.js
Antes de crear un proyecto Vue necesitas tener Node.js instalado en tu ordenador. Node.js incluye npm (Node Package Manager), que es la herramienta que usarás para instalar dependencias y ejecutar comandos del proyecto.
Ve a nodejs.org y descarga la versión LTS (Long Term Support). Es la versión estable y recomendada. La instalación es un asistente clásico de "siguiente, siguiente, instalar" — no tiene misterio.
Una vez instalado, abre una terminal y verifica que funciona:
node --version
# → v24.x.x (o similar)
npm --version
# → 11.x.x (o similar)
Si ambos comandos devuelven un número de versión, estás listo. Si no, reinicia la terminal — a veces el sistema necesita reconocer los nuevos comandos.
Crear un proyecto Vue con Vite
Vue utiliza Vite como herramienta de desarrollo. Vite es un bundler ultrarrápido que arranca tu servidor de desarrollo en milisegundos (en proyectos grandes, herramientas anteriores podían tardar 30 segundos o más). No necesitas instalarlo por separado — viene integrado cuando creas un proyecto Vue.
Abre tu terminal y ejecuta:
npm create vue@latest
Si es la primera vez que lo ejecutas, npm te preguntará si quieres instalar el paquete create-vue. Escribe y y pulsa Enter:
Need to install the following packages:
[email protected]
Ok to proceed? (y) → y
Después se lanza un asistente interactivo. Pon el nombre del proyecto, di que no a TypeScript, no selecciones ninguna feature y no saltes el código de ejemplo:
◇ Project name (target directory):
│ cafe-estelar-vue
│
◇ Use TypeScript?
│ No
│
◇ Select features to include in your project:
│ none
│
◇ Select experimental features to include in your project:
│ none
│
◇ Skip all example code and start with a blank Vue project?
│ No
No seleccionamos ninguna feature por ahora. No es que no sean útiles — lo son, y las iremos añadiendo a medida que las necesitemos (Router en la lección 09, por ejemplo). Pero empezar con un proyecto limpio te permite entender Vue sin distracciones.
Ahora entra en la carpeta del proyecto, instala las dependencias y arranca el servidor de desarrollo:
cd cafe-estelar-vue
npm install
npm run dev
Verás algo como esto en la terminal:
VITE v7.x.x ready in 400 ms
➜ Local: http://localhost:5173/
➜ Network: use --host to expose
➜ Vue DevTools: Press Alt(⌥)+Shift(⇧)+D in App to toggle the Vue DevTools
Abre la URL que aparece junto a Local en tu navegador (normalmente http://localhost:5173/, aunque si ese puerto está ocupado Vite elegirá otro automáticamente, como 5174). Verás la página de bienvenida de Vue. Tu primer proyecto Vue está corriendo.
Editor recomendado: Zed
Para trabajar con Vue te recomiendo Zed como editor de código. Es rápido, moderno y tiene soporte nativo para Vue sin necesidad de instalar extensiones adicionales. Abre la carpeta cafe-estelar-vue en Zed y estarás listo para trabajar.
Estructura del proyecto
Abre la carpeta del proyecto en tu editor. Verás algo así:
cafe-estelar-vue/
├── index.html ← La única página HTML de la aplicación
├── package.json ← Dependencias y scripts del proyecto
├── vite.config.js ← Configuración de Vite
├── public/ ← Archivos estáticos (favicon, imágenes)
├── src/ ← Tu código vive aquí
│ ├── main.js ← Punto de entrada de la aplicación
│ ├── App.vue ← Componente raíz
│ ├── components/ ← Tus componentes reutilizables
│ └── assets/ ← Recursos (CSS, imágenes)
Vamos a ver los archivos más importantes:
index.html — El punto de partida
Esta es la única página HTML que el navegador carga. Fíjate en el <div id="app">:
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Vite App</title>
</head>
<body>
<div id="app"></div>
<script type="module" src="/src/main.js"></script>
</body>
</html>
Ese <div id="app"> es donde Vue va a "montar" toda tu aplicación. Todo el contenido dinámico se genera dentro de ese contenedor.
src/main.js — El arranque
Este archivo crea la instancia de Vue y la conecta con el <div id="app"> del HTML:
import './assets/main.css'
import { createApp } from 'vue'
import App from './App.vue'
createApp(App).mount('#app')
Primero importa los estilos base del proyecto. Después importa Vue, importa tu componente raíz (App.vue) y lo monta en el elemento con id app. Simple y directo.
src/App.vue — Tu primer componente
Este es el archivo más importante por ahora. Es un Single File Component (SFC): un archivo .vue que contiene todo lo necesario para un componente en un solo lugar.
Anatomía de un Single File Component
Un archivo .vue tiene tres bloques:
<script setup>
// Aquí va tu lógica JavaScript
// Variables, funciones, imports...
</script>
<template>
<!-- Aquí va tu HTML -->
<!-- Es lo que el usuario ve en pantalla -->
</template>
<style scoped>
/* Aquí va tu CSS */
/* "scoped" significa que estos estilos solo afectan a este componente */
</style>
<script setup>— Tu lógica: datos reactivos, funciones, imports. El atributosetupes la sintaxis moderna de Vue que hace el código más limpio y directo.<template>— Tu HTML: lo que se renderiza en pantalla. Aquí puedes usar sintaxis especial de Vue como{{{ }}}para mostrar datos.<style scoped>— Tu CSS: estilos que solo aplican a este componente. Elscopedevita que tus estilos "se escapen" y afecten a otros componentes.
Es como tener HTML, CSS y JavaScript en un solo archivo, pero organizado y encapsulado. Cada componente es una pieza independiente de tu interfaz.
Tu primer componente reactivo
Vamos a reemplazar el contenido de App.vue con algo propio. Borra todo lo que hay y escribe esto:
<script setup>
import { ref } from 'vue'
const nombre = ref('Astronauta')
const pedidos = ref(0)
function nuevoPedido() {
pedidos.value++
}
</script>
<template>
<div class="cafeteria">
<h1>Café Estelar</h1>
<p class="saludo">¡Bienvenido, {{ nombre }}!</p>
<div class="pedidos">
<p>Pedidos realizados: <strong>{{ pedidos }}</strong></p>
<button @click="nuevoPedido">Pedir un café</button>
</div>
<div class="nombre">
<label>Tu nombre:</label>
<input v-model="nombre" placeholder="Escribe tu nombre" />
</div>
</div>
</template>
<style scoped>
.cafeteria {
max-width: 500px;
margin: 60px auto;
padding: 40px;
font-family: system-ui, sans-serif;
text-align: center;
}
h1 {
color: #4FC08D;
font-size: 2rem;
margin-bottom: 8px;
}
.saludo {
font-size: 1.25rem;
color: #333;
margin-bottom: 32px;
}
.pedidos {
margin-bottom: 32px;
}
.pedidos p {
font-size: 1.1rem;
margin-bottom: 12px;
}
button {
background: #4FC08D;
color: white;
border: none;
padding: 12px 24px;
border-radius: 8px;
font-size: 1rem;
cursor: pointer;
transition: background 0.2s;
}
button:hover {
background: #3daf7c;
}
.nombre {
display: flex;
flex-direction: column;
gap: 8px;
align-items: center;
}
label {
font-size: 0.9rem;
color: #666;
}
input {
padding: 10px 16px;
border: 2px solid #ddd;
border-radius: 8px;
font-size: 1rem;
text-align: center;
width: 250px;
transition: border-color 0.2s;
}
input:focus {
outline: none;
border-color: #4FC08D;
}
</style>
Guarda el archivo y mira el navegador — Vite actualiza la página automáticamente sin que tengas que recargar (eso se llama Hot Module Replacement).
Vamos a desglosar lo que acaba de pasar:
Los datos reactivos con ref()
import { ref } from 'vue'
const nombre = ref('Astronauta')
const pedidos = ref(0)
ref() crea una variable reactiva. Cuando su valor cambia, Vue actualiza automáticamente cualquier parte de la interfaz que la esté usando. El valor inicial que le pasas ('Astronauta', 0) es el estado inicial.
Dentro de <script setup>, accedes al valor con .value (por ejemplo, pedidos.value++). Pero dentro de <template>, Vue desenvuelve el ref automáticamente — por eso escribes {{ pedidos }} y no {{ pedidos.value }}.
Interpolación con {{ }}
<p>¡Bienvenido, @{{ nombre }}!</p>
<p>Pedidos realizados: <strong>{{ pedidos }}</strong></p>
Las dobles llaves {{ }} insertan el valor de una variable reactiva en el HTML. Cuando el valor cambia, el texto se actualiza solo. Es la forma más básica de mostrar datos en Vue.
Eventos con @click
<button @click="nuevoPedido">Pedir un café</button>
@click es la forma de Vue de decir "cuando el usuario haga clic, ejecuta esta función". Es equivalente a addEventListener("click", ...) de JavaScript vanilla, pero mucho más limpio. La @ es un atajo de v-on:.
Binding bidireccional con v-model
<input v-model="nombre" placeholder="Escribe tu nombre" />
v-model conecta el input con la variable nombre en ambas direcciones: si cambias la variable, el input se actualiza; si el usuario escribe en el input, la variable se actualiza. Pruébalo: escribe tu nombre en el campo y mira cómo el saludo cambia en tiempo real.
Con JavaScript vanilla necesitarías un addEventListener("input", ...) más un querySelector más un textContent = .... Con Vue es una sola directiva: v-model.
Resumen
En esta lección has aprendido:
- Vue es un framework progresivo para construir interfaces de usuario, creado por Evan You.
- Una SPA carga una sola página HTML y JavaScript se encarga de la navegación y el renderizado.
- La reactividad es la característica estrella de Vue: cambias los datos y la interfaz se actualiza sola.
- Se crea un proyecto con
npm create vue@latest, que usa Vite como bundler. - Un archivo
.vue(SFC) tiene tres bloques:<script setup>,<template>y<style scoped>. ref()crea variables reactivas,@{{ }}muestra datos en el template,@clickmaneja eventos yv-modelconecta inputs con datos.
En la siguiente lección vamos a profundizar en la reactividad y aprenderás a trabajar con datos más complejos como objetos y arrays reactivos.
Tu primer componente Vue: saludo y contador
Crea un proyecto Vue nuevo con Vite (usando npm create vue@latest) y modifica App.vue para que tenga lo siguiente:
- Un campo de texto donde el usuario pueda escribir su nombre. Usa
v-modelpara conectarlo a una variable reactiva. - Un saludo personalizado que diga "¡Hola, [nombre]! Bienvenido a Café Estelar" y se actualice en tiempo real mientras escribe.
- Un contador de cafés pedidos que empiece en 0. Un botón "Pedir café" que incremente el contador cada vez que se pulse.
- Un mensaje condicional: si el contador llega a 5 o más, muestra el texto "¡Eres un cliente VIP!" debajo del contador. Pista: puedes usar
v-ifcon la condición directamente en el template, así:v-if="cafes >= 5".
Bonus: añade un botón "Reiniciar" que ponga el contador a 0 y el nombre de vuelta al valor por defecto.
lightbulb Pistas
Recuerda que dentro de <script setup> accedes al valor de un ref con .value (por ejemplo, cafes.value = 0), pero dentro del <template> Vue lo desenvuelve automáticamente. Para el v-if, simplemente añádelo como atributo en un elemento: <p v-if="cafes >= 5">¡Eres un cliente VIP!</p>.