Vue 3 Reactivity Transform en 2026: $ref, $computed y Preguntas de Entrevista

Guía completa sobre Reactivity Transform de Vue 3, incluyendo $ref, $computed, macros de reactividad y preguntas frecuentes en entrevistas técnicas.

Vue 3 Reactivity Transform con $ref y $computed

Reactivity Transform de Vue 3 representa una evolución significativa en la forma de trabajar con la reactividad. Esta característica experimental, introducida para simplificar la sintaxis del Composition API, ha pasado por varias iteraciones antes de alcanzar su forma actual en 2026. Comprender su funcionamiento, ventajas y limitaciones constituye un conocimiento esencial para cualquier desarrollador Vue que busque dominar los conceptos avanzados del framework.

Estado del Reactivity Transform en 2026

Reactivity Transform fue oficialmente estabilizado en Vue 3.5. Las macros $ref, $computed y $shallowRef están disponibles a través de un plugin dedicado de Vite, separado del core de Vue.

Entendiendo el Problema que Resuelve Reactivity Transform

El Composition API estándar de Vue 3 requiere el uso de .value para acceder y modificar valores reactivos creados con ref(). Esta sintaxis, aunque explícita, introduce una carga cognitiva adicional y puede generar bugs sutiles cuando el desarrollador olvida usar .value.

typescript
import { ref, computed } from 'vue'

// Sintaxis estándar del Composition API
const count = ref(0)
const doubled = computed(() => count.value * 2)

function increment() {
  count.value++ // .value requerido
}

console.log(doubled.value) // .value requerido también

Reactivity Transform elimina esta necesidad transformando automáticamente el código en tiempo de compilación. Las variables declaradas con macros de reactividad se comportan como variables JavaScript normales mientras conservan su naturaleza reactiva.

Las Macros $ref y $computed

Las macros $ref y $computed constituyen el núcleo de Reactivity Transform. Permiten declarar valores reactivos sin necesidad de manipular .value manualmente.

vue
<script setup>
// Con Reactivity Transform
let count = $ref(0)
const doubled = $computed(() => count * 2)

function increment() {
  count++ // No se necesita .value
}

console.log(doubled) // Acceso directo
</script>

<template>
  <button @click="increment">{{ count }} (doubled: {{ doubled }})</button>
</template>

El compilador de Vue transforma este código a sintaxis estándar con ref() y .value antes de la ejecución. Esta transformación es transparente para el desarrollador y no modifica el comportamiento del código.

Cómo Funciona la Transformación

El compilador analiza el código y aplica las siguientes transformaciones:

  1. $ref(value) se convierte en ref(value)
  2. Los accesos a la variable se convierten en variable.value
  3. Las asignaciones se convierten en variable.value = newValue
typescript
// Código fuente con Reactivity Transform
let message = $ref('Hola')
message = 'Adiós'
console.log(message)

// Código transformado por el compilador
const message = ref('Hola')
message.value = 'Adiós'
console.log(message.value)

Configuración de Reactivity Transform con Vite

La activación de Reactivity Transform requiere una configuración específica en el proyecto Vue. En 2026, esta funcionalidad se proporciona a través del plugin @vue/reactivity-transform.

vite.config.tstypescript
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import { reactivityTransform } from '@vue/reactivity-transform'

export default defineConfig({
  plugins: [
    vue(),
    reactivityTransform()
  ]
})

Para proyectos que utilizan TypeScript, una configuración adicional asegura el reconocimiento de los tipos de las macros.

tsconfig.jsonjson
{
  "compilerOptions": {
    "types": ["@vue/reactivity-transform"]
  }
}

$shallowRef y Otras Macros Avanzadas

Además de $ref y $computed, Reactivity Transform incluye otras macros para casos de uso específicos.

vue
<script setup>
import { watchEffect } from 'vue'

// $shallowRef para objetos grandes
let largeObject = $shallowRef({ data: [], metadata: {} })

// Solo la referencia es reactiva, no las propiedades internas
largeObject = { data: [1, 2, 3], metadata: { updated: true } }

// $toRef para convertir una prop a ref
const props = defineProps<{ initialValue: number }>()
let value = $(props.initialValue) // Equivalente a toRef(props, 'initialValue')

watchEffect(() => {
  console.log('Value changed:', value)
})
</script>

La Macro $() para Desestructuración Reactiva

La macro $() permite desestructurar objetos reactivos mientras se preserva la reactividad de cada propiedad extraída.

vue
<script setup>
import { reactive } from 'vue'

const state = reactive({
  firstName: 'Juan',
  lastName: 'García',
  age: 30
})

// Desestructuración con preservación de reactividad
const { firstName, lastName } = $(state)

// firstName y lastName siguen siendo reactivos
function updateName() {
  firstName = 'Pedro' // Modifica state.firstName
}
</script>

Integración con Composables

Reactivity Transform se integra naturalmente con composables, simplificando su uso y creación.

composables/useCounter.tstypescript
export function useCounter(initial = 0) {
  let count = $ref(initial)
  const doubled = $computed(() => count * 2)
  const isEven = $computed(() => count % 2 === 0)

  function increment() {
    count++
  }

  function decrement() {
    count--
  }

  function reset() {
    count = initial
  }

  // $$() convierte las refs a objetos ref estándar para el retorno
  return $$({ count, doubled, isEven, increment, decrement, reset })
}

El uso del composable se vuelve más intuitivo.

vue
<script setup>
import { useCounter } from '@/composables/useCounter'

// Desestructuración con $() para mantener la reactividad
const { count, doubled, increment, reset } = $(useCounter(10))
</script>

<template>
  <div>
    <p>Count: {{ count }} (Doubled: {{ doubled }})</p>
    <button @click="increment">+</button>
    <button @click="reset">Reset</button>
  </div>
</template>

Manejo de Props con Reactivity Transform

La conversión de props a refs reactivas modificables localmente representa un caso de uso frecuente de Reactivity Transform.

vue
<script setup>
const props = defineProps<{
  modelValue: string
  disabled?: boolean
}>()

const emit = defineEmits<{
  'update:modelValue': [value: string]
}>()

// Creación de una ref local vinculada a la prop
let localValue = $ref(props.modelValue)

// Sincronización bidireccional
watch(
  () => props.modelValue,
  (newVal) => { localValue = newVal }
)

watch(
  () => localValue,
  (newVal) => { emit('update:modelValue', newVal) }
)
</script>

<template>
  <input v-model="localValue" :disabled="disabled" />
</template>

Preguntas de Entrevista Técnica sobre Reactivity Transform

Las entrevistas técnicas de Vue 3 frecuentemente incluyen preguntas sobre Reactivity Transform. Las siguientes preguntas representan los temas más comúnmente abordados.

Pregunta 1: ¿Cuál es la diferencia entre $ref y ref?

Respuesta esperada: $ref es una macro de compilación que genera código usando ref() con acceso automático a .value. La diferencia es puramente sintáctica a nivel de código fuente. En tiempo de ejecución, ambos producen el mismo resultado. $ref mejora la ergonomía del desarrollador eliminando la necesidad de escribir .value manualmente.

Pregunta 2: ¿Por qué usar $$() al retornar valores desde un composable?

Respuesta esperada: La macro $$() convierte las variables transformadas por Reactivity Transform a objetos ref estándar. Sin esta conversión, los valores retornados serían primitivas que perderían su reactividad. $$() asegura que el consumidor del composable reciba refs reactivas que puede usar con $() para desestructuración.

Pregunta 3: ¿Funciona Reactivity Transform con Options API?

Respuesta esperada: No. Reactivity Transform está diseñado exclusivamente para el Composition API con <script setup>. Se basa en el análisis estático del código en tiempo de compilación, lo cual no es compatible con la estructura dinámica del Options API.

Pregunta 4: ¿Cómo depurar código que usa Reactivity Transform?

Respuesta esperada: El código fuente visible en las herramientas de desarrollo es el código transformado, no el código original. Para depurar efectivamente, se recomienda usar source maps y comprender la transformación aplicada. Vue DevTools muestra correctamente los valores reactivos independientemente de la sintaxis utilizada.

typescript
// Para ver la ref subyacente durante la depuración
let count = $ref(0)
console.log($$(count)) // Muestra el objeto ref completo

Pregunta 5: ¿Cuáles son las trampas comunes de Reactivity Transform?

Respuesta esperada: Las trampas principales incluyen:

  • Olvidar $$() al retornar valores desde funciones
  • Mezclar sintaxis estándar y sintaxis transformada en el mismo archivo
  • Asumir que todas las operaciones JavaScript funcionan idénticamente (algunas asignaciones complejas pueden requerir atención especial)
  • No configurar correctamente TypeScript para reconocer los tipos de las macros

Comparación con la Sintaxis Estándar

Una comparación directa ilustra las diferencias entre ambos enfoques.

vue
<!-- Sin Reactivity Transform -->
<script setup>
import { ref, computed, watch } from 'vue'

const items = ref<string[]>([])
const filter = ref('')
const filteredItems = computed(() =>
  items.value.filter(item => item.includes(filter.value))
)

function addItem(item: string) {
  items.value.push(item)
}

watch(filter, (newFilter) => {
  console.log('Filter changed:', newFilter)
})
</script>
vue
<!-- Con Reactivity Transform -->
<script setup>
import { watch } from 'vue'

let items = $ref<string[]>([])
let filter = $ref('')
const filteredItems = $computed(() =>
  items.filter(item => item.includes(filter))
)

function addItem(item: string) {
  items.push(item)
}

watch($$(filter), (newFilter) => {
  console.log('Filter changed:', newFilter)
})
</script>

¿Listo para aprobar tus entrevistas de Vue.js / Nuxt.js?

Practica con nuestros simuladores interactivos, flashcards y tests técnicos.

Buenas Prácticas y Recomendaciones

La adopción de Reactivity Transform en un proyecto existente requiere un enfoque metódico para mantener la consistencia del código.

Consistencia dentro del proyecto: Elegir un enfoque (estándar o transformado) y aplicarlo uniformemente. Mezclar ambas sintaxis complica la lectura y mantenimiento del código.

Documentación explícita: Documentar el uso de Reactivity Transform en el README del proyecto y guías de contribución. Los nuevos desarrolladores deben comprender la sintaxis utilizada.

Pruebas unitarias: Las pruebas funcionan idénticamente sin importar la sintaxis utilizada, ya que el código se transforma antes de la ejecución. No se requieren modificaciones a las pruebas existentes durante la migración.

Migración progresiva: Para proyectos existentes, migrar archivo por archivo en lugar de convertir todo simultáneamente. Este enfoque reduce el riesgo de introducir bugs.

Reactivity Transform representa una mejora significativa en la ergonomía del desarrollo con Vue 3. Su dominio demuestra una comprensión profunda del sistema de reactividad de Vue y constituye una ventaja en entrevistas técnicas para posiciones de desarrollador Vue senior.

Reto diario

¿Sabrías detectar el bug en Vue.js / Nuxt.js?

Un fragmento real, un bug oculto, un intento al día. Sin cuenta para probar.

Anthony Fillion-Maillet

Escrito por

Anthony Fillion-Maillet

Fundador de SharpSkill

Desarrollador fullstack desde hace más de 10 años. Dirige SharpSkill y responde por todo lo que se publica aquí.

Actualizado el 9 de septiembre de 2026

Etiquetas

#vue 3
#reactivity transform
#composition api
#entrevista técnica

Compartir

Artículos relacionados