¿Qué es Vue?
Vue es un framework de JavaScript progresivo para construir interfaces de usuario. La palabra es deliberada: puedes integrar Vue en una sola página para mejorar un widget, o utilizarlo con una herramienta de construcción para crear una aplicación completa. No es necesario reescribir el código para obtener valor, y el framework crece según tus necesidades.
En esencia, Vue consta de dos elementos: una sintaxis de plantillas que extiende HTML y un sistema de reactividad que rastrea tus datos y actualiza la vista automáticamente. Tú declaras qué debe mostrar la UI y Vue se encarga de mantenerla sincronizada.
Single-file components
Un componente de Vue normalmente reside en un archivo .vue con tres bloques: un template, un script y estilos. Mantenerlos juntos convierte al componente en una unidad única y autónoma.
<!-- Card.vue -->
<script setup>
defineProps({ title: String });
</script>
<template>
<article class="card">
<h3>{{ title }}</h3>
<slot />
</article>
</template>
<style scoped>
.card {
border-radius: 1rem;
padding: 1.5rem;
}
</style>
<style scoped> limita automáticamente el CSS a este componente, evitando que los nombres de las clases se filtren hacia afuera. <script setup> es una macro del compilador que hace que la Composition API sea concisa y es el estándar moderno.
Sintaxis de plantillas
Las plantillas de Vue son HTML con un pequeño conjunto de directivas. La interpolación utiliza llaves dobles y las directivas son atributos prefijados con v-.
<!-- profile.vue -->
<template>
<h1>{{ user.name }}</h1>
<p v-if="user.online">Online</p>
<p v-else>Offline</p>
<ul>
<li v-for="post in posts" :key="post.id">
{{ post.title }}
</li>
</ul>
<img :src="user.avatar" :alt="user.name" />
<button @click="follow">Follow</button>
</template>
Lee las abreviaciones de la siguiente manera: :src vincula un atributo a una expresión y @click escucha un evento. v-if renderiza condicionalmente y v-for realiza bucles con un :key para actualizaciones eficientes. La plantilla se compila en funciones de renderizado, aunque rara vez necesitarás verlas.
Reactividad: ref y reactive
El sistema de reactividad de Vue supervisa tus datos y vuelve a renderizar la interfaz cuando estos cambian. En la Composition API, creas valores reactivos con ref o reactive.
<script setup>
import { ref, reactive } from "vue";
const count = ref(0); // .value in script
const user = reactive({ // proxy, no .value
name: "Ada",
online: true,
});
function increment() {
count.value += 1;
}
</script>
ref envuelve cualquier valor y se accede a él a través de .value en el script, aunque las plantillas lo desempaquetan automáticamente por ti. reactive devuelve un proxy profundamente reactivo para un objeto. Una convención común es utilizar ref de manera consistente, ya que funciona con primitivos y es fácil de reasignar.
Computed y watch
Existen dos funciones para manejar valores derivados y efectos secundarios.
<script setup>
import { ref, computed, watch } from "vue";
const items = ref([10, 20, 30]);
const total = computed(() =>
items.value.reduce((sum, n) => sum + n, 0),
);
watch(items, (next, prev) => {
console.log("items changed", prev, next);
});
</script>
computed almacena su resultado en caché y lo recalcula solo cuando cambia una dependencia; úsalo siempre que un valor derive de otro estado. watch ejecuta un callback cuando cambia una fuente y se utiliza para efectos secundarios como el logging, peticiones de datos o guardado. Un error común es recurrir a watch para calcular un valor.
Props, emits y slots
Los datos fluyen hacia abajo a través de props y hacia arriba mediante eventos emitidos.
<!-- Child.vue -->
<script setup>
const props = defineProps({
label: { type: String, required: true },
});
const emit = defineEmits(["select"]);
function handleClick() {
emit("select", props.label);
}
</script>
<template>
<button @click="handleClick">{{ label }}</button>
</template>
<!-- Parent.vue -->
<Child label="Save" @select="onSelect" />
Las props son de solo lectura en el componente hijo, lo que mantiene la fuente de verdad en el padre. Los slots permiten que un padre pase marcado a un hijo, el equivalente a children de React.
Composables
La mayor ventaja de la Composition API es la lógica reutilizable. Un composable es una función que utiliza reactividad y devuelve un estado, nombrada con el prefijo use.
// useFetch.js
import { ref, watchEffect } from "vue";
export function useFetch(url) {
const data = ref(null);
const error = ref(null);
watchEffect(async () => {
data.value = null;
error.value = null;
try {
const res = await fetch(url.value);
data.value = await res.json();
} catch (err) {
error.value = err;
}
});
return { data, error };
}
Los composables comparten la lógica, no el estado, por lo que cada componente que llama a useFetch obtiene sus propios datos independientes. Este es el equivalente en Vue a un custom hook.
Enrutamiento y estado
Vue Router gestiona la navegación mediante un mapeo declarativo de URL a componente, y Pinia es el store oficial para el estado compartido.
// router.js
import { createRouter, createWebHistory } from "vue-router";
export const router = createRouter({
history: createWebHistory(),
routes: [
{ path: "/", component: Home },
{ path: "/users/:id", component: UserProfile },
],
});
Utiliza un store cuando varios componentes distantes necesiten el mismo estado. Para datos locales o entre padres e hijos, las props y los composables suelen ser suficientes.
Mejores prácticas
- Usa
script setupy la Composition API para el código nuevo. - Prefiere
computedsobrewatchpara los valores derivados. - Mantén las props como solo lectura y emite eventos para los cambios.
- Extrae la lógica reutilizable en composables.
- Usa estilos
scoped, o CSS Modules, para mantener los estilos locales. - Nombra los composables con el prefijo
use. - Evita acceder al estado de los componentes hijos; comunícate a través de props y emits.
Errores comunes
- Olvidar
.valueen una ref dentro de script. - Usar
watchpara calcular un valor quecomputeddebería derivar. - Mutar props en un componente hijo en lugar de emitir un evento.
- Desestructurar un objeto
reactivey perder la reactividad. - Poner todo el estado en un store global cuando el estado local sería suficiente.
- Mezclar la Options API y la Composition API sin una razón clara.
Próximos pasos
Vue es una puerta de entrada sencilla a los frameworks de componentes y es capaz de escalar en cualquier proyecto. Añade Nuxt para el renderizado en el servidor y convenciones de routing, compara este enfoque con React y Svelte, y mantén tus conocimientos de JavaScript al día. Después, construye algo pequeño —una lista filtrable o un formulario con validación— y deja que la reactividad haga el trabajo por ti.