Skip to content
← Todas las preguntas
Avanzado

¿Cuál es la diferencia entre computed y watch?

ReactividadComposition API

Ambos reaccionan a cambios en datos reactivos, pero sirven para propósitos fundamentalmente distintos. Equivocarse lleva a estado duplicado (usar watch donde computed bastaría) o efectos secundarios inesperados (usar computed para cosas que no deberían ser puras).

computed: derivar valores

Un computed calcula un valor a partir de otros datos reactivos. Tiene caché — Vue solo lo recalcula cuando sus dependencias cambian realmente. Se lee como una variable, nunca se llama como una función.

vue
<script setup lang="ts">
import { ref, computed } from 'vue'

const firstName = ref('Ana')
const lastName = ref('García')

const fullName = computed(() => `${firstName.value} ${lastName.value}`)
// fullName.value === 'Ana García'
// Se recalcula solo cuando firstName o lastName cambian
</script>

<template>
  <p>{{ fullName }}</p>
</template>

Piensa en computed como una fórmula en una celda de hoja de cálculo. Celda C1 = A1 + B1. No la "ejecutas" — simplemente siempre tiene la respuesta correcta.

watch: reaccionar a cambios

Un watch ejecuta código en respuesta a un cambio. No devuelve un valor — realiza efectos secundarios como llamadas a la API, manipulación del DOM, escrituras en localStorage o eventos de analítica.

ts
import { ref, watch } from 'vue'

const searchQuery = ref('')

watch(searchQuery, async (newQuery, oldQuery) => {
  if (newQuery.length < 3) return
  const results = await fetch(`/api/search?q=${newQuery}`)
  // Actualizar resultados, registrar analítica, etc.
})

Recibes tanto el valor nuevo como el anterior, y puedes hacer trabajo asíncrono dentro. Un computed no puede hacer ninguna de las dos cosas.

La regla de decisión

Pregúntate: "¿Estoy calculando un valor o haciendo algo?"

PreguntaRespuestaUsar
¿Necesito un valor derivado en la plantilla?computed
¿Necesito obtener datos cuando algo cambia?watch
¿Necesito el valor anterior?watch
¿Necesito escribir en localStorage/cookies?watch
¿Puede el resultado expresarse como una función pura de las entradas?computed

El error más común

Usar watch + ref para hacer lo que computed hace de forma gratuita:

ts
// ❌ Sincronización manual con watch — estado duplicado, fácil de desincronizar
const items = ref<Item[]>([])
const activeCount = ref(0)

watch(items, (val) => {
  activeCount.value = val.filter(i => i.active).length
}, { deep: true })

// ✅ Usa computed — siempre sincronizado, con caché, sin estado extra
const activeCount = computed(() => items.value.filter(i => i.active).length)

Si te encuentras escribiendo un watch que asigna un ref a un valor derivado, reemplázalo con un computed.

Ver también: ¿Cuál es la diferencia entre watch y watchEffect? · ¿Cuál es la diferencia entre ref y reactive?

Referencias

Publicado bajo la licencia MIT.