Capítulo 1 de 11

Tutorial VueJS 3 – Crear una aplicación Vue

verificado el 7 septiembre 2026 · 5 min

Respuesta rápida

Crea el proyecto con npm create vue@latest, responde «no» a TypeScript y luego lanza npm install y npm run dev. Una aplicación Vue nace de createApp(App).mount('#app'), un dato declarado con ref() se muestra en la plantilla entre llaves dobles y se actualiza solo.

Al final de este capítulo, tendrás un proyecto Vue 3 funcionando y sabrás mostrar un dato reactivo en pantalla.

Una aplicación Vue es una instancia creada por createApp y enganchada a un elemento de la página. Este capítulo instala el proyecto y después muestra un primer dato en pantalla.

Crear el proyecto

Vue trae un generador oficial, create-vue, que monta un proyecto Vite configurado para Vue. Abre un terminal en la carpeta donde guardas tus proyectos:

bash
npm create vue@latest

El generador hace una serie de preguntas. Para este tutorial, responde:

  • Project name: boutique-vue
  • TypeScript: No, nos quedamos en JavaScript para no mezclar dos aprendizajes.
  • JSX, Vue Router, Pinia, ESLint, Prettier: No. Los añadiremos cuando hagan falta.
  • Vitest: si quieres escribir tests, si no No.
Cuidado con la opción –default

Muchos tutoriales indican npm create vue@latest -- --default para «ir rápido». En create-vue 3.23, ese flag activa TypeScript: acabas con un src/main.ts y ficheros tsconfig, que no es lo que buscas aquí. Mejor responde a las preguntas.

Instala las dependencias y arranca el servidor de desarrollo:

npm install falla con el npm incluido en Node 22

En Node 22, el npm incluido (10.9) se detiene con npm error Cannot read properties of null (reading 'edgesOut'), tanto en un proyecto nuevo como con el código de este tutorial. Actualice npm antes de instalar: npm install -g npm@latest. Node 24 no tiene este problema.

bash
cd boutique-vue
npm install
npm run dev

Vite muestra una dirección, normalmente http://localhost:5173/. Ábrela: aparece la página de inicio del proyecto.

Lo que ha creado el generador

bash
boutique-vue/
├── index.html          ← la seule vraie page HTML du site
├── package.json
├── vite.config.js
├── public/             ← fichiers servis tels quels
└── src/
    ├── main.js         ← point d’entrée : crée et monte l’application
    ├── App.vue         ← composant racine
    ├── assets/
    └── components/

Tres archivos cuentan por ahora. El generador también crea src/assets/main.css y base.css, el estilo de su página de inicio: podrá borrarlos, junto con la línea import './assets/main.css' que abre src/main.js, cuando el CSS del tutorial los sustituya al final del capítulo.

index.html contiene un contenedor vacío y carga el punto de entrada. Nada más: el resto de la página lo produce Vue.

index.html
<body>
  <div id="app"></div>
  <script type="module" src="/src/main.js"></script>
</body>

src/main.js crea la aplicación a partir del componente raíz y la monta en ese contenedor.

src/main.js
import './assets/main.css'

import { createApp } from 'vue'
import App from './App.vue'

createApp(App).mount('#app')

createApp(App) construye la instancia, .mount('#app') le entrega el elemento del DOM que tiene derecho a gestionar. A partir de ahí, todo lo que está dentro de <div id="app"> pertenece a Vue.

El primer componente

Un fichero .vue es un componente monofichero: el script, la plantilla y el estilo de una misma parte de la interfaz viven en el mismo sitio. Vacía src/App.vue y escribe:

src/App.vue
<script setup>
import { ref } from 'vue'

const product = ref('T-Shirt')
</script>

<template>
  <div class="product-display">
    <h1>{{ product }}</h1>
  </div>
</template>

Guarda: el navegador muestra «T-Shirt» sin recargar. Es el reemplazo de módulos en caliente de Vite.

Este fichero irá creciendo hasta el capítulo sobre los componentes, donde lo trocearemos.

Entender estas siete líneas

<script setup> le indica a Vue que ese bloque describe la lógica del componente. Todo lo que declares ahí en el primer nivel se puede usar en la plantilla, sin exportar nada.

ref('T-Shirt') crea una referencia reactiva: una caja que guarda un valor y avisa a Vue cuando cambia. En el script, la caja se abre con .value:

javascript
const product = ref('T-Shirt')

console.log(product.value)   // 'T-Shirt'
product.value = 'Pull'       // el título cambia inmediatamente en pantalla

En la plantilla, en cambio, se escribe {{ product }} sin .value: Vue desenvuelve la referencia automáticamente.

Las llaves dobles son una interpolación. Aceptan cualquier expresión JavaScript, no solo un nombre de variable:

html
<h1>{{ product }}</h1>
<h1>{{ product.toUpperCase() }}</h1>
<h1>{{ 'Notre ' + product }}</h1>

La reactividad, en concreto

Cambia el valor inicial por 'Pull' y guarda: el título lo sigue. No has escrito ni una línea para buscar el h1 y cambiar su contenido. Ese es el núcleo de Vue: tú describes lo que la página debe mostrar en función del estado y Vue se encarga de la actualización.

En Options API

El mismo componente se escribiría export default { data() { return { product: 'T-Shirt' } } }, y el script accedería con this.product. Con <script setup>, this no existe: solo hay variables.

¿Y las demás herramientas de build?

create-vue instala Vite, la herramienta que recomienda el equipo de Vue. Otros empaquetadores también compilan los ficheros .vue: Parcel mediante @parcel/transformer-vue, o webpack con vue-loader.

Funcionan, pero son más lentos y se salen del camino trillado. Medido el 2 de septiembre de 2026 sobre la misma aplicación de un solo componente:

bash
Vite 8.2.2     build en  1,05 s   →  60,57 kB  (23,91 kB gzip)
Parcel 2.16.4  build en 10,57 s   →  92,77 kB

El resultado de npm run build es una carpeta de ficheros estáticos. Lo que haya dentro decide tu posicionamiento, un tema que se trata aparte.

Quédate con Vite para un proyecto nuevo. Las alternativas solo se justifican si tu cadena de build actual ya depende de ellas.

El CSS del tutorial

Para que la aplicación tenga algo de aspecto, crea src/assets/boutique.css con las pocas reglas que se usan a lo largo de los capítulos:

src/assets/boutique.css
.product-display { display: flex; gap: 32px; padding: 24px; font-family: system-ui, sans-serif; }
.product-image img { width: 240px; }
.variants-wrapper { display: flex; gap: 10px; }
.color-circle { width: 50px; height: 50px; margin-top: 8px; border: 2px solid #d8d8d8; border-radius: 50%; cursor: pointer; }
.button { border: none; background: #1d4ed8; color: #fff; padding: 10px 18px; border-radius: 6px; cursor: pointer; }
.disabledButton { background-color: #d8d8d8; cursor: not-allowed; }

E impórtalo en el punto de entrada:

src/main.js
import './assets/boutique.css'
import { createApp } from 'vue'
import App from './App.vue'

createApp(App).mount('#app')
EjercicioAñade un dato brand con el valor «Gekkode» y muéstralo en el título, delante del nombre del producto. Después cambia su valor en el código y comprueba que la página se actualiza sin recargar.

Errores frecuentes

npm create vue@latest -- --default instala TypeScript En create-vue 3.23, el flag --default activa TypeScript: acabas con un src/main.ts y ficheros tsconfig. Lanza el comando sin flag y responde «no» a la pregunta sobre TypeScript.
Olvidar .value en el script ref() devuelve un objeto. En el script escribe product.value, en la plantilla basta con {{ product }}, Vue desenvuelve la referencia.
Una versión de Node demasiado antigua create-vue exige Node 22.18 o superior. Compruébalo con node -v antes de crear el proyecto.
Newsletter

Las nuevas pruebas, tutoriales y proyectos, por correo.

Pruebas reproducibles, código versionado, resultados fechados. Nunca spam.