En el ecosistema de Vue.js, la reactividad es el motor que permite que la interfaz de usuario se actualice automáticamente cuando los datos cambian. Mientras que en Vue 2 la reactividad se definía implícitamente dentro de la opción data, Vue 3 introduce la Composition API, proporcionando herramientas explícitas como ref y reactive para manejar el estado.
Uso de ref para valorres primitivos y objetos
La función ref es la forma principal de crear referencias reactivas. Aunque es ideal para tipos de datos primitivos (String, Number, Boolean), también puede manejar objetos complejos.
import { ref } from 'vue';
// Definición de una referencia reactiva
const puntuacion = ref(10);
Características principales:
- Retorna un objeto de tipo
RefImpldonde el valor real reside en la propeidad.value. - En el bloque
<script>, es obligatorio acceder mediantevariable.value. - En el
<template>, Vue realiza un desempaquetado automático, por lo que no es necesario usar.value.
<template>
<div class="contenedor">
<h2>Usuario: {{ apodo }}</h2>
<h2>Nivel: {{ nivel }}</h2>
<button @click="subirNivel">Subir Nivel</button>
<button @click="actualizarApodo">Cambiar Nombre</button>
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue';
let apodo = ref('Codificador');
let nivel = ref(1);
function actualizarApodo() {
apodo.value = 'Arquitecto_JS';
}
function subirNivel() {
nivel.value++;
}
</script>
Uso de reactive para estructuras de datos complejas
La función reactive está diseñada específicamente para objetos y arreglos. A diferencia de ref, no requiere el uso de .value para acceder a las propiedades del objeto.
Puntos clave:
- Retorna un
Proxydel objeto original. - Proporciona reactividad profunda (deep reactivity), afectando a todas las propiedades anidadas.
- No se puede usar con valores primitivos (lanzará una advertencia o no funcionará como se espera).
<template>
<div class="contenedor">
<h3>Dispositivo: {{ smartphone.modelo }} - RAM: {{ smartphone.memoria }}GB</h3>
<button @click="ampliarRam">Añadir RAM</button>
<ul>
<li v-for="app in aplicaciones" :key="app.id">{{ app.nombre }}</li>
</ul>
<button @click="instalarApp">Instalar Nueva App</button>
</div>
</template>
<script setup lang="ts">
import { reactive } from 'vue';
const smartphone = reactive({
modelo: 'X-Phone 15',
memoria: 8
});
const aplicaciones = reactive([
{ id: 1, nombre: 'Navegador' },
{ id: 2, nombre: 'Correo' }
]);
function ampliarRam() {
smartphone.memoria += 4;
}
function instalarApp() {
aplicaciones.push({ id: Date.now(), nombre: 'Nueva Aplicación' });
}
</script>
Diferencias y Limitaciones
Aunque ambos mecanismos logran la reactividad, existen diferencias operativas críticas:
- Reasignación: Si intentas reasignar un objeto completo declarado con
reactive, perderás la conexión reactiva. Para actualizar un objetoreactivepor completo, se recomienda usarObject.assign. - Versatilidad:
refes más versátil ya que acepta cualquier tipo de dato. Cuando se le pasa un objeto aref, este invoca internamente areactivepara la propiedadvalue.
<template>
<div class="contenedor">
<p>Configuración actual: {{ config.tema }} (Versión: {{ config.version }})</p>
<button @click="resetearConfig">Resetear Configuración</button>
<hr>
<p>Contador Global: {{ contador }}</p>
<button @click="incrementar">+1</button>
</div>
</template>
<script setup lang="ts">
import { ref, reactive } from 'vue';
let config = reactive({ tema: 'Oscuro', version: '1.0.0' });
let contador = ref(0);
function incrementar() {
contador.value++;
}
function resetearConfig() {
// config = { tema: 'Claro', version: '0.0.0' }; // INCORRECTO: Rompe la reactividad
// CORRECTO: Mantiene la referencia original del Proxy
Object.assign(config, { tema: 'Claro', version: '0.0.0' });
}
</script>
Criterios de elección
Como regla general en el desarrollo profesional:
- Utiliza
refpara datos primitivos de manera obligatoria. - Para objetos y arreglos, puedes usar
refsi prefieres mantener una sitnaxis consistente con.value, oreactivesi buscas una sintaxis más limpia y trabajas con estructuras de datos complejas o anidadas. - Si necesitas reasignar la raíz de un objeto con frecuencia,
refes la opción más sencilla ya que permitevariable.value = { ... nuevo objeto }sin perder la reactividad.