En el ecosistema de Vue 3, el sistema de reactividad es un pilar fundamental que permite a las aplicaciones responder dinámicamente a los cambios de estado. La Composition API, introducida en Vue 3, ofrece dos funciones clave para declarar estados reactivos: ref y reactive. Aunque ambas cumplen un propósito similar de hacer que los datos sean reactivos, están diseñadas para diferentes escenarios y tipos de datos.
ref: Envoltura Reactiva para Cualquier Tipo de Valor
La función ref es una herramienta versátil que permite crear una referencia reactiva a cualquier valor, ya sea un tipo primitivo (como un número, una cadena de texto, un booleano) o un objeto complejo. Cuando se utiliza ref, Vue envuelve el valor proporcionado en un objeto que expone una propiedad .value. Es a través de esta propiedad .value que se accede y se modifica el valor subyacente de la referencia reactiva.
Una característica notable de ref es su "desenvolvimiento automático" (auto-unwrapping) cuando se utiliza dentro de las plantillas de Vue (templates). Esto significa que no es necesario acceder explícitamente a .value dentro de <template>, lo que simplifica su uso.
Ejemplos de Uso de ref:
1. Creación de una Referencia Sencilla:
Para gestionar un contador simple o cualquier dato primitivo:
import { ref } from 'vue';
const contadorGlobal = ref(0);
// Para acceder/modificar fuera de las plantillas, se usa .value
// console.log(contadorGlobal.value); // 0
// contadorGlobal.value++; // Incrementa el valor a 1
2. Manipulación de Elementos del DOM con ref:
Puede usarse para obtener una referencia a un elemento DOM específico después de que el componente se monte.
import { ref, onMounted } from 'vue';
export default {
setup() {
const cuadroTextoRef = ref(null);
onMounted(() => {
if (cuadroTextoRef.value) {
cuadroTextoRef.value.focus(); // Enfoca el input al montar el componente
}
});
return {
cuadroTextoRef
};
}
};
<template>
<input type="text" ref="cuadroTextoRef" placeholder="Este input se enfocará" />
</template>
3. Interacción en Componentes Vue:
Un ejemplo que muestra cómo ref puede interactuar con la lógica del componente.
import { ref } from 'vue';
export default {
setup() {
const estadoMensaje = ref('¡Hola desde Vue!');
function cambiarMensaje() {
estadoMensaje.value = '¡Mensaje actualizado!';
}
return {
estadoMensaje,
cambiarMensaje
};
}
};
<template>
<div>
<p>{{ estadoMensaje }}</p> <!-- Desenvolvimiento automático -->
<button @click="cambiarMensaje">Modificar Mensaje</button>
</div>
</template>
reactive: Proxy Reactivo para Objetos y Arrays
La función reactive está diseñada específicamente para convertir objetos JavaScript planos o arrays en proxies reactivos. Cuando se accede o se modifica una propiedad de un objeto reactive, Vue detecta automáticamente los cambios y actualiza la interfaz de usuario. A diferencia de ref, reactive no requiere la propiedad .value para acceder o modificar sus propiedades; se trabaja directamente con el objeto.
Es importante destacar que reactive no puede envolver tipos primitivos directamente. Si se le pasa un primitivo, Vue emitirá una advertencia y el valor no será reactivo. Además, si se reasigna un objeto reactive completo con un nuevo objeto, se perderá la reactividad del objeto original.
Ejemplos de Uso de reactive:
1. Creación de un Objeto de Datos Reactivo:
Ideal para estados complejos que agrupan múltiples propiedades.
import { reactive } from 'vue';
const datosUsuario = reactive({
nombre: 'Alicia',
edad: 28,
estaActivo: true,
intereses: ['programación', 'lectura']
});
// Para acceder a una propiedad: console.log(datosUsuario.nombre);
// Para modificar una propiedad: datosUsuario.edad++;
2. Modificación y Uso en Plantillas:
Cómo interactuar con un objeto reactive dentro de un componente.
import { reactive } from 'vue';
export default {
setup() {
const configuracionApp = reactive({
temaOscuro: false,
notificacionesActivadas: true
});
function alternarTema() {
configuracionApp.temaOscuro = !configuracionApp.temaOscuro;
}
return {
configuracionApp,
alternarTema
};
}
};
<template>
<div>
<p>Tema Oscuro: {{ configuracionApp.temaOscuro ? 'Activado' : 'Desactivado' }}</p>
<p>Notificaciones: {{ configuracionApp.notificacionesActivadas ? 'Sí' : 'No' }}</p>
<button @click="alternarTema">Cambiar Tema</button>
</div>
</template>
3. Usando reactive en Ciclos de Vida:
Demostración de acceso a datos reactivos en un hook de ciclo de vida.
import { reactive, onMounted } from 'vue';
export default {
setup() {
const estadoJuego = reactive({
puntuacion: 0,
nivel: 1
});
onMounted(() => {
console.log(`Juego inicializado: Nivel ${estadoJuego.nivel}, Puntuación ${estadoJuego.puntuacion}`);
// Podrías cargar datos o iniciar lógica aquí
});
return {
estadoJuego
};
}
};
ref vs. reactive: Una Comparación Detallada
La elección entre ref y reactive a menudo depende del tipo de dato y el contexto de uso. Comprender sus diferencias fundamentales es crucial para escribir código Vue 3 eficiente y claro.
Tabla Comparativa:
| Característica | ref |
reactive |
|---|---|---|
| Propósito Principal | Crea una referencia reactiva para cualquier tipo de valor (primitivos y objetos). | Crea un proxy reactivo para objetos planos y arrays. |
| Acceso al Valor | Se accede a través de la propiedad .value fuera de las plantillas. |
Se accede directamente a las propiedades del objeto. |
| Comportamiento en Plantillas | Se desenvuelve automáticamente; no se necesita .value. |
Se accede directamente a las propiedades del objeto (miObjeto.propiedad). |
| Reasignación del Valor | Se puede reasignar el .value a un nuevo objeto/primitivo sin perder reactividad. |
Si se reasigna el objeto reactive completo, se pierde la reactividad del objeto original. (Es mejor modificar propiedades internas). |
| Uso Recomendado | Para valores primitivos individuales o cuando se necesita pasar la reactividad de un solo valor. | Para agrupar múltiples propiedades de estado relacionadas en un solo objeto. |
| Flexibilidad | Más flexible, puede contener cualquier tipo de dato. | Menos flexible, diseñado solo para objetos y arrays. |
En resumen, ref es ideal para manejar valores individuales y primitivos, ofreciendo flexibilidad con su propiedad .value y desenvolvimiento automático en plantillas. Por otro lado, reactive brilla al gestionar estados complejos compuestos por múltiples propiedades de objetos o colecciones, donde la interacción directa con las propiedades es más natural. A menudo, en proyectos reales, se utiliza una combinación de ambas funciones para estructurar el estado de manera óptima.