Comprende con claridad cómo funciona el ciclo de vida en Composition API y cuándo usar funciones internas como setup, onMounted y onUpdated para cargar datos, manipular el DOM y optimizar la lógica con propiedades computadas. Aquí encontrarás ejemplos prácticos con reactividad y buenas prácticas para que tu componente de View sea claro y eficiente.
¿Cómo cambia el ciclo de vida en Composition API frente a Options API?
A diferencia del Options API, en Composition API no declaras opciones como created, beforeCreate o mounted. Todo parte de una sola función: setup. Lo que escribas dentro de setup ocurre en el equivalente a created/beforeCreate: ya hay información reactiva disponible, pero el DOM aún no está montado.
setup equivale a created/beforeCreate: lógica inicial y acceso a datos reactivos.
DOM no disponible en setup: evita depender de elementos montados.
Funciones internas con prefijo on: onBeforeMount, onMounted, onUpdated, etc., para responder a cada etapa.
¿Qué hacer en setup, onMounted y updated para cada caso?
Elegir el momento adecuado evita errores y hace tu componente más simple. Usa setup para cargar datos, onMounted para trabajar con el DOM, y onUpdated para reaccionar a cambios ya reflejados en la interfaz.
¿Cómo cargar datos con fetch en setup?
En setup puedes realizar un fetch a una API y poblar una referencia reactiva. Primero vacía la lista y luego asigna los datos recibidos a su .value.
<script setup>
import { ref, onMounted } from 'vue'
const productos = ref([])
// Carga inicial: ocurre en el ciclo equivalente a created/beforeCreate.
fetch('URL_DE_TU_API')
.then(res => res.json())
.then(data => {
productos.value = [] // vaciar referencia.
productos.value = data // asignar datos de la API.
})
.catch(err => console.error(err))
// Acceso a productos en la vista se hará de forma reactiva.
</script>
¿Qué realizar después del montaje con onMounted?
Cuando el componente ya se montó en el navegador, puedes interactuar con el DOM o ejecutar tareas que requieren elementos presentes.
<script setup>
import { onMounted } from 'vue'
onMounted(() => {
console.log('mounted: componente listo en el navegador')
// Aquí podrías medir nodos, enfocar inputs o integrar librerías del DOM.
})
</script>
¿Cuándo elegir updated?
Cuando necesitas ejecutar lógica después de que un cambio reactivo ya impactó el DOM.
Úsalo con moderación: puede dispararse muchas veces.
¿Cómo aplicar propiedades computadas para filtrar productos?
Propón un reto con reactividad: crear un input que capture lo que escribe el usuario y, con una propiedad computada, filtrar la lista de productos sin mutar el original. Así aprovechas referencias reactivas, eventos del teclado y computed.
<template>
<input
type="text"
placeholder="Buscar producto..."
@input="consulta = $event.target.value"
/>
<ul>
<li v-for="p in productosFiltrados" :key="p.id">
{{ p.nombre }} - {{ p.precio }}
</li>
</ul>
</template>
<script setup>
import { ref, computed } from 'vue'
const productos = ref([]) // se llena con la API en setup.
const consulta = ref('') // texto que escribe el usuario.
const productosFiltrados = computed(() => {
const q = consulta.value.trim().toLowerCase()
if (!q) return productos.value
return productos.value.filter(p =>
String(p.nombre || '').toLowerCase().includes(q)
)
})
</script>
Puntos clave que refuerzan habilidades prácticas:
Reactividad con referencias: usa ref y accede con .value.
Propiedades computadas: recalculan vistas derivadas sin duplicar estado.
Eventos del teclado: captura @input (o @keyup) para actualizar la búsqueda.
Ciclos de vida con funciones internas: setup para datos, onMounted para DOM, onUpdated para post-actualizaciones.
Trabajo con API y JSON: convierte respuesta a JSON y asigna a tu estado reactivo.
¿Tienes una solución distinta para el filtrado o un caso especial con mounted/updated? Cuéntalo en los comentarios y comparte tu enfoque.
Reto listo, no sé muy bien en dónde se usaría la computed, ya que desde mi punto de vista no hace falta, pero yo la use para trackear cuando el valor de products cambie y en lugar de usar a products dentro del ```forestoy usando la computedallProducts``:
.
Primero este es mi input que ejecuta la búsqueda cuando el usuario presiona enter:
El tema es que así estas consultado a la API por cada busqueda que realizas, por lo que puede afectar el rendimiento. Es mejor filtrar sobre el array que ya tiene descargada toda la información y que retorne otro array con solo lo filtrado, y sobre ese es que vas a iterar en el v-for.
En composition API, la función setup, reemplaza las funciones de beforeCreated, created. Las funciones del ciclo de vida que serán utilizadas, deben ser llamadas dentro de composition API para poderlas utilizar.
usando composition API:
en el HTML
// Para el filtro<input type="text" placeholder="Ingrese texto a filtrar" v-model="search"/>// Para mostrar los productos<main><product
v-for="product in filteredProducts":key="product.name":product="product" @sendtocart="addToCart($event)"></product></main>
Agregar al setup()
const filterState =reactive({search:'',filteredProducts:computed(()=>{if(filterState.search===''){return products.value;}else{return products.value.filter((product)=>{return product.name.toLowerCase().includes(filterState.search);});}})});```
Y luego exportarlo:
...toRefs(filterState),
Quise hacerlo con el @keyup.enter pero el computed no se actualizaba ya que no estaba actualizando el array principal de products, y si mutaba ese array luego si se borraba el filtro de búsqueda tenía que mostrar todo el array original, por eso mejor no tocar el array principal y sólo mostrar lo que vas filtrando, y el computed funciona ya que se está observando el search del filterState.
¿Qué diferencia existe entre el onMounted y el onUpdated?
El onUpdated sería similar al de React y cada que se actualice algo internamente en el componente se ejecutaría? o sólo se ejecuta "la primera vez" como el onMounted?
¡Gracias!
onMounted es cuando el componente ya está montado en el DOM, este solo se ejecuta una vez, y el onUpdated se ejecuta cada vez que el componente se actualiza :D
<product v-if="filter" v-for="product in filteredProduct":key="product.id":product="product" @sendtocart="addToCart($event)"></product><product v-else v-for="product in products":key="product.name":product="product" @sendtocart="addToCart($event)"></product>
primero condicione la renderización del item, si hay un producto dentro del arreglo de filteredProduct entonces se rederiza ese bloque, si no entonces se renderiza la lista completa.
este código primero conecta "search" a un input con v-model, de esa forma sabermos que esta colocando el usuario, despues recorre el nombre de los elementos en products, y si alguno incluye el valor de search entonces se guarda en filteredProduct y filter se vuelve true, si lo que hay es un string vacio, entonces filter vuelve false, asi condicione la renderizacion
La verdad no entiendo porque el profesor recomienda usar una computed. No se como la computed tendria cabida en el reto, yo lo hice con una function normal, v-model, y capturando el evento.
Me encanta todas las soluciones, pero como recién comienzo con vue, para options API lo hice así:
Template
<section><input type="search" id="site-search" name="query" v-model="word" placeholder="Ingresar Producto"><button @click="search()">Buscar<img src="./images/search-icon.svg" alt="icono de buscar" height="12"/></button></section><Product v-for="product in filterProducts":key="product.name":product="product" @sendtocart="addToCar($event)"/>
Y el v-for itero es sobre el productsFiltered ya no sobre products.
El tema es que para no hacer tanta cosa, se debe escribir el nombre completo del articulo. La idea más adelante seria hacer una busqueda no exclusiva, donde pueda buscar por palabras separadas y ver si coincide alguna con alguna parte del nombre del articulo.
Eso será para otra ocasión...
entonces a diferencia de Options API, en Composition API todo va dentro de setup() ???