Skip to content

Todo para WordPress, el desarrollo web — y mucho más

⚡ Aprendiendo las bases de Vue 3: de una carpeta vacía a componentes

⚡ Aprendiendo las bases de Vue 3: de una carpeta vacía a componentes

Está frente a Vue 3 y ve un framework de frontend pulido, del grupo de los tres grandes. React, Angular, Vue: suena serio. Luego abre el primer tutorial, y ahí lo esperan vite, create-vue y archivos .vue con transpiladores... Aunque en realidad puede incluir Vue con una sola línea <script> y empezar a escribir código de inmediato. Sin bundlers, sin JSX, sin infierno de configuración.

La brecha entre «quiero probarlo» y «escribí un componente» es más corta aquí que en cualquier otro lado. Pero la mayoría de los tutoriales no cierran esa brecha; repiten la documentación en fragmentos sin darle el panorama completo. Usted ve pedazos de sintaxis sueltos y no logra entender cómo se convierten en una aplicación.

Esta guía es el camino exacto que nosotros mismos recorrimos con Vue: desde una carpeta vacía hasta componentes con props. Usted escribirá y ejecutará cada línea por su cuenta. Sin magia, solo código que funciona y comprensión de la reactividad, el principal superpoder de Vue.

💡 Resumen rápido:

  • Construya una app Vue desde un CDN y móntela en el DOM: su primera instancia funcional en 5 minutos
  • Recorra cuatro directivas clave, v-for, v-if, v-on y v-bind: los pilares de cualquier plantilla Vue
  • Desglose computed y methods: cuándo cachear y cuándo invocar
  • Extraiga lógica en componentes y pase datos mediante props: un paso hacia una arquitectura real

Crear una aplicación Vue

Comencemos desde cero absoluto. Nada de create-vue, vite o vue-cli, solo una carpeta con dos archivos.

Cree el directorio y los archivos en su terminal:

1mkdir vue3-intro
2cd vue3-intro
3touch index.html app.js

O haga lo mismo mediante su gestor de archivos. Ahora abra index.html y escriba el esqueleto:

1<!DOCTYPE html>
2<html lang="ru">
3<head>
4 <meta charset="UTF-8">
5 <meta name="viewport" content="width=device-width, initial-scale=1.0">
6 <script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
7 <title>Vue 3 — first steps</title>
8</head>
9<body>
10 <div id="app"></div>
11 <script src="./app.js"></script>
12</body>
13</html>

Tres líneas clave. <script src="https://unpkg.com/vue@3/dist/vue.global.js"> carga Vue 3 desde un CDN. Esta es la forma más rápida de empezar: la librería se carga como un archivo JavaScript común, sin necesidad de paso de compilación. <div id="app"> establece el punto de montaje: el lugar en el DOM donde Vue «vivirá». La tercera línea importa app.js, donde definiremos la lógica.

Ahora completemos app.js:

1const app = Vue.createApp({
2 data() {
3 return {
4 course: 'Introduction to Vue 3'
5 }
6 }
7})
8
9app.mount('#app')

El método Vue.createApp() crea una instancia de aplicación. Recibe un objeto de opciones; aquí declaramos una propiedad course mediante la función data(). Vue vuelve reactiva cada propiedad retornada por data(): cuando un valor cambia, el DOM se actualiza automáticamente. No se necesita manipulación manual del árbol.

Pero la aplicación necesita «engancharse» a un elemento de la página. Eso es lo que hace app.mount('#app'). Sin esta línea, Vue no reaccionará a ningún cambio: la instancia está creada pero no iniciada.

Solo falta mostrar la propiedad en el HTML. Dentro de <div id="app">, escriba:

1<h1>{{ course }}</h1>

Las llaves dobles {{ }} son interpolación, la forma principal de mostrar datos en las plantillas de Vue. Todo lo que está dentro de {{ }} es reemplazado por Vue con el valor de la propiedad correspondiente de data().

First Vue 3 app in the browser

Abra index.html en su navegador. La página muestra el texto. Su primera aplicación está lista, y la escribió usted mismo en lugar de generarla mediante una CLI.

Renderizar listas

En una aplicación real, usted casi siempre trabaja con arreglos: productos, etiquetas, publicaciones. Vue proporciona la directiva v-for para esto.

Agreguemos un arreglo de etiquetas a data():

1const app = Vue.createApp({
2 data() {
3 return {
4 course: 'Introduction to Vue 3',
5 description: 'Basic guide to Vue 3 for beginners',
6 price: '$19.99',
7 tags: ['Vue', 'Frontend', 'JavaScript']
8 }
9 }
10})

Y en el HTML, una lista:

1<ul>
2 <li v-for="tag in tags">{{ tag }}</li>
3</ul>

La directiva v-for itera sobre el arreglo tags y crea su propio <li> para cada elemento. La variable tag dentro del bucle es el elemento actual. El resultado se ve así:

Vue 3 tag list using the v-for directive

Un matiz importante: al iterar sobre un arreglo, cada elemento del DOM necesita una clave única. Vue la usa para rastrear la identidad de los nodos durante las actualizaciones, lo que acelera el rerenderizado y previene errores relacionados con el estado.

1<ul>
2 <li v-for="(tag, index) in tags" :key="index">{{ tag }}</li>
3</ul>

:key es la abreviatura de v-bind:key, que vincula el atributo key al valor del índice. Si tiene un arreglo de objetos, por ejemplo { id: 1, name: 'Vue' }, use id como clave en lugar del índice. El índice cambia al reordenar, mientras que id es estable, lo que lo hace más confiable.

Renderizado condicional

A menudo necesita mostrar u ocultar un elemento según una condición: un botón de compra solo si el curso está disponible. Vue maneja esto con la directiva v-if.

Agreguemos una bandera available a data():

1data() {
2 return {
3 course: 'Introduction to Vue 3',
4 description: 'Basic guide to Vue 3 for beginners',
5 price: '$19.99',
6 available: true,
7 tags: [
8 { id: 1, name: 'Vue' },
9 { id: 2, name: 'Frontend' },
10 { id: 3, name: 'JavaScript' }
11 ]
12 }
13}

Y usémosla en el marcado:

1<p v-if="available">Course available for purchase!</p>
2<p v-else>Unfortunately, the course is currently unavailable.</p>

v-if evalúa la expresión entre comillas. Si es verdadera, se renderiza el primer bloque; de lo contrario, se activa v-else. Pruebe ejecutar app.available = false en la consola del navegador y observe cómo la página reacciona al instante.

Conditional rendering in Vue 3 with v-if

Además de v-if / v-else, también existen v-else-if para cadenas de condiciones y v-show. La diferencia es fundamental: v-if elimina por completo el elemento del DOM, mientras que v-show solo alterna display: none. Elija v-if cuando la condición cambie rara vez. Use v-show para alternancias frecuentes como pestañas, donde el rendimiento es importante.

Manejo de eventos

La directiva v-on, o @ para abreviar, escucha eventos del DOM: clics, entrada de texto, desplazamiento del cursor. Cuando un evento se dispara, Vue ejecuta el método o la expresión especificada.

Agreguemos un método purchase a las opciones de la aplicación:

1const app = Vue.createApp({
2 data() {
3 return {
4 course: 'Introduction to Vue 3',
5 description: 'Basic guide to Vue 3 for beginners',
6 price: '$19.99',
7 available: true,
8 tags: [
9 { id: 1, name: 'Vue' },
10 { id: 2, name: 'Frontend' },
11 { id: 3, name: 'JavaScript' }
12 ]
13 }
14 },
15 methods: {
16 purchase() {
17 console.log('Course purchased!')
18 }
19 }
20})

La sección methods contiene funciones accesibles en la plantilla y en otros métodos mediante this. Ahora vinculemos la llamada a un botón:

1<button @click="purchase">Buy</button>
Handling a click in Vue 3 with v-on

Para acciones simples, puede escribir código directamente en @click:

1<button @click="available = !available">Toggle availability</button>
Toggling button state in Vue 3

El código en línea como este es práctico para operaciones cortas, como alternar un indicador. Pero traslade siempre la lógica compleja a métodos; la plantilla debe seguir siendo legible. Una regla sencilla: counter += 1 está bien en la plantilla, pero diez líneas de lógica de compra deben ir en un método.

Vinculación de atributos

Atributos como src, href o alt a menudo necesitan ser dinámicos. La directiva v-bind, o : de forma abreviada, vincula el valor de un atributo a una expresión de Vue.

Agreguemos datos para una imagen:

1data() {
2 return {
3 // ...other properties
4 imgURL: 'https://catalins.tech/img',
5 imgDescription: 'Photo of a desk with a computer'
6 }
7}

En la plantilla, vincúlelos a un <img>:

1<img :src="imgURL" :alt="imgDescription" width="500" height="350">

La forma completa sería v-bind:src="imgURL"; los dos puntos son simplemente azúcar sintáctico. Vue ahora rastrea imgURL e imgDescription: cámbielos en data() y la imagen en la página se actualiza automáticamente. Eso es la reactividad en acción.

Binding image attributes with v-bind

El mismo principio se aplica a atributos como :href, :disabled y :class, así como a cualquier otro. Pruébelo usted mismo: añada un enlace con un href dinámico desde data() y confirme que funciona sin una sola línea adicional.

Propiedades computadas

A veces los datos necesitan transformarse antes de mostrarse: formatear un precio, concatenar nombre y apellido, verificar una condición. Vue ofrece las propiedades computed para esto.

Imagine que siempre quiere tener una descripción de imagen, incluso si el campo imgDescription está vacío. Escribamos una propiedad computada:

1const app = Vue.createApp({
2 data() {
3 return {
4 course: 'Introduction to Vue 3',
5 description: 'Basic guide to Vue 3 for beginners',
6 price: '$19.99',
7 available: true,
8 imgURL: 'https://catalins.tech/img',
9 imgDescription: 'Photo of a desk with a computer',
10 tags: [
11 { id: 1, name: 'Vue' },
12 { id: 2, name: 'Frontend' },
13 { id: 3, name: 'JavaScript' }
14 ]
15 }
16 },
17 computed: {
18 hasImageDescription() {
19 return this.imgDescription.length > 0
20 ? this.imgDescription
21 : 'Automatic image description'
22 }
23 }
24})

Ahora use la propiedad computada en la plantilla en lugar del dato sin procesar:

1<img :src="imgURL" :alt="hasImageDescription" width="500" height="350">

Vue almacena en caché el resultado de una propiedad computed y solo la recalcula cuando cambian sus dependencias, en nuestro caso imgDescription. Esto es más eficiente que llamar a una función en cada renderizado.

Una regla importante: las propiedades computadas están pensadas para mostrar datos, no para modificarlos. No altere el estado de la aplicación dentro de computed; use métodos para eso.

Métodos frente a propiedades computadas

La diferencia entre methods y computed se reduce a una pregunta: ¿está modificando datos o mostrando un valor derivado?

Las propiedades computadas son para la capa de presentación. Formateo, filtrado, verificación de condiciones, concatenación de cadenas. Se almacenan en caché y no tienen efectos secundarios.

Los métodos son para acciones. Cambiar un valor en data(), enviar una solicitud, alternar un indicador. Se llaman explícitamente y pueden hacer cualquier cosa.

Un anti-patrón típico es modificar this.course dentro de una propiedad computed. Una propiedad computada reacciona a los cambios en course, pero no debería modificarlo ella misma. Use siempre un método para modificar datos. Deje que la plantilla describa «qué mostrar», no «cómo calcularlo».

Componentes y props

A medida que una aplicación crece, mantener todo en un solo archivo se vuelve inmanejable. Vue le permite dividir la interfaz en componentes: bloques aislados con su propia lógica, plantilla y estilos.

Creemos nuestro primer componente, CourseCard:

1mkdir components
2touch components/CourseCard.js

En components/CourseCard.js, defina el componente:

1app.component('coursedisplay', {
2 data() {
3 return {
4 course: 'Introduction to Vue 3',
5 description: 'Basic guide to Vue 3 for beginners',
6 price: '$19.99',
7 available: true,
8 imgURL: 'https://catalins.tech/img',
9 imgDescription: 'Photo of a desk with a computer',
10 tags: [
11 { id: 1, name: 'Vue' },
12 { id: 2, name: 'Frontend' },
13 { id: 3, name: 'JavaScript' }
14 ]
15 }
16 },
17 computed: {
18 hasImageDescription() {
19 return this.imgDescription.length > 0
20 ? this.imgDescription
21 : 'Automatic image description'
22 }
23 },
24 template: `
25 <img :src="imgURL" :alt="hasImageDescription" width="500" height="350">
26 <h1>{{ course }}</h1>
27 <p>{{ description }}</p>
28 <p>{{ price }}</p>
29 <button @click="available = !available">Buy</button>
30 <ul>
31 <li v-for="tag in tags" :key="tag.id">{{ tag.name }}</li>
32 </ul>
33 <p v-if="available">Course available for purchase!</p>
34 <p v-else>Unfortunately, the course is currently unavailable.</p>
35 `
36})

El primer argumento de app.component() es el nombre que usaremos en HTML como etiqueta: <coursedisplay></coursedisplay>. El segundo es un objeto con data(), computed y template, las «partes internas» del componente.

Ahora incluyamos el componente en index.html y usémoslo:

1<div id="app">
2 <coursedisplay></coursedisplay>
3</div>
4<script src="./app.js"></script>
5<script src="./components/CourseCard.js"></script>
6<script>
7 const mountedApp = app.mount('#app')
8</script>

Importamos el archivo del componente, lo usamos como una etiqueta personalizada y montamos la aplicación directamente en el HTML. La lógica del curso ahora está encapsulada dentro de CourseCard, mientras que app.js solo se encarga de crear la instancia.

Props: pasar datos entre componentes

Las props (abreviatura de properties) son el mecanismo para pasar datos de un componente padre a uno hijo. El componente hijo declara qué props acepta, y el padre las pasa como atributos.

Agreguemos una prop paid a CourseCard que indique si el curso es de pago o gratuito:

1app.component('coursedisplay', {
2 props: {
3 paid: {
4 type: Boolean
5 }
6 },
7 // ...rest of the configuration
8})

El padre, en nuestro caso app.js, pasa el valor:

1const app = Vue.createApp({
2 data() {
3 return {
4 allCourses: 1,
5 paid: true
6 }
7 }
8})

Y en index.html, pasamos la prop así:

1<coursedisplay :paid="paid"></coursedisplay>

Vue valida automáticamente el tipo del valor pasado. Si se espera un Boolean pero se recibe una cadena, el framework emitirá una advertencia en la consola. Esto le ahorra errores tontos a medida que la base de código crece.

Para hacer que una prop sea obligatoria, agregue required: true a su definición. Vue se quejará entonces si el padre no pasa un valor, así que usted se enterará del problema antes de que rompa la interfaz.

Puede encontrar el código completo de esta guía en el repositorio vue3-intro en GitHub, que contiene los archivos terminados index.html, app.js y components/CourseCard.js. Hágale un fork y experimente.

Video relacionado

Para reforzar el material con práctica, vea la primera lección del curso de Vue 3 de Net Ninja; complementa bien esta guía con una demostración de código en vivo:

⁉️🤔 Preguntas frecuentes

¿Puedo usar Vue 3 sin un bundler en producción?

Sí, incluirlo mediante CDN (unpkg.com/vue@3/dist/vue.global.js) también funciona en producción. Pero para proyectos reales recomendamos pasarse a Vite: obtiene tree-shaking, división de código y componentes de archivo único (SFC), que simplifican drásticamente el desarrollo a medida que la aplicación crece. La plantilla inicial npm create vue@latest configura todo esto en un minuto.

¿En qué se diferencia v-if de v-show?

v-if elimina por completo el elemento del DOM cuando la condición es falsa. v-show mantiene el elemento en el DOM pero alterna la propiedad CSS display: none. Use v-if cuando la condición cambie rara vez, por ejemplo, el rol de usuario. Use v-show para alternancias frecuentes como pestañas, donde la velocidad de renderizado importa y quiere evitar recrear nodos.

¿Es obligatorio:key en v-for?

Técnicamente v-for funciona sin :key, pero Vue emitirá una advertencia en la consola. Sin una key, el framework no puede rastrear qué elemento del DOM corresponde a qué elemento de datos, lo que provoca errores durante el reordenamiento y la eliminación. Especifique siempre :key con un identificador único, el id de sus datos en lugar del índice del array.

¿Cuál es la diferencia entre data() y computed?

data() almacena el estado original, los datos «en bruto». computed deriva un valor a partir de ellos para mostrarlo: una cadena formateada, un array filtrado, un resultado de validación. Una propiedad computada se actualiza automáticamente cuando cambian sus dependencias y se almacena en caché entre renderizados. Los métodos, en cambio, se llaman de nuevo cada vez y están pensados para acciones, no para mostrar datos.

¿Se puede mezclar la Options API y la Composition API?

Sí, puede usar ambos estilos en un mismo proyecto. Vue 3 soporta completamente la Options API, mientras que la Composition API es una herramienta adicional para escenarios complejos. Para aprender, recomendamos empezar con la Options API: es más estructurada y se acerca más al modelo mental de «un componente es un objeto con opciones».

Qué hacer a continuación: su próximo paso con Vue 3

Ha construido su primera aplicación, explorado directivas, propiedades computadas y componentes. Esta es la base sobre la que se construye cualquier proyecto, desde una landing page hasta un panel de administración.

Hay tres caminos por delante. Primero, consolide mediante la práctica: tome una API pública como JSONPlaceholder y muestre una lista de publicaciones con filtrado mediante computed. Segundo, muévase a Vite y archivos .vue: la documentación oficial de Vue 3 lo guiará desde create-vue hasta su primer SFC en una hora. Tercero, aprenda Vue Router y Pinia para construir una SPA completa.

Si desea probar Vue sin necesidad de instalar nada, consulte el artículo sobre cómo incluir Vue mediante CDN. El código inicial de esta guía se encuentra en el repositorio vue3-intro; haga un fork y experimente.