0Pricing
Vue Academy · Lección

Componente Vue Suspense

con slots default y #fallback, carga de componentes asíncronos y Suspense anidado

Componente Vue Suspense es una lección gratuita de Vue Academy en CoddyKit. Esta es la lección 1 de 4. Puedes leer la lección completa abajo gratuitamente — luego la practicas en el navegador con un editor de código integrado y un tutor de IA 24/7. Forma parte de la ruta de aprendizaje de Vue Academy, y tu progreso se sincroniza en la web y la app de CoddyKit. El curso de Vue Academy incluye 4 lecciones en total.

Qué resuelve Suspense

Suspense es un componente integrado de Vue que coordina los estados de carga de los componentes que tienen dependencias asíncronas.

Sin él, cada componente asíncrono gestiona su propio indicador de carga. Con Suspense, declara un único límite que espera a todo el trabajo asíncrono anidado y muestra un único contenido alternativo hasta que todo está listo.

Dos slots: default y fallback

Suspense expone dos slots con nombre:

  • default — el contenido real, que puede contener componentes asíncronos o un setup() asíncrono
  • fallback — lo que se muestra mientras se resuelve el slot default

Cuando se resuelven todas las dependencias asíncronas, Vue sustituye el fallback por el contenido default.

<template>
  <Suspense>
    <template #default>
      <UserDashboard />
    </template>
    <template #fallback>
      <div class="spinner">Loading dashboard...</div>
    </template>
  </Suspense>
</template>

setup() asíncrono como dependencia

Un componente se convierte en una dependencia asíncrona cuando su función setup() se declara como async y espera algo mediante await. Vue realiza el seguimiento de la promesa devuelta.

El equivalente de <script setup> consiste en utilizar await de nivel superior directamente dentro del bloque.

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

// Top-level await makes this an async dependency of Suspense
const res = await fetch('/api/profile')
const profile = ref(await res.json())
</script>

<template>
  <h1>Welcome, {{ profile.name }}</h1>
</template>

Los componentes asíncronos también cuentan

Los componentes creados con defineAsyncComponent también reciben seguimiento de Suspense. El fallback permanece visible hasta que se resuelve el import() dinámico.

Esto permite dividir en partes los componentes pesados sin tener que escribir una interfaz de carga específica para cada componente.

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

const Chart = defineAsyncComponent(() =>
  import('./HeavyChart.vue')
)
</script>

<template>
  <Suspense>
    <Chart />
    <template #fallback>Preparing chart...</template>
  </Suspense>
</template>

Espera conjunta de varios hijos asíncronos

Si el slot default contiene varias dependencias asíncronas, Suspense espera a que todas ellas se resuelvan antes de mostrar el contenido.

Esto evita el desplazamiento del diseño que se produce cuando los componentes aparecen uno a uno.

<template>
  <Suspense>
    <div>
      <UserStats />   <!-- async setup -->
      <RecentOrders /> <!-- async setup -->
      <Recommendations /> <!-- async component -->
    </div>
    <template #fallback>
      <PageSkeleton />
    </template>
  </Suspense>
</template>

Capturar rechazos con onErrorCaptured

Si un setup() asíncrono es rechazado (por ejemplo, debido a un fetch fallido), el error se propaga hasta el hook onErrorCaptured más cercano de un componente padre.

Suspense no muestra errores por sí mismo, por lo que debe combinarlo con un boundary de errores.

<script setup>
import { ref, onErrorCaptured } from 'vue'

const error = ref(null)

onErrorCaptured((err) => {
  error.value = err
  return false // stop the error from propagating further
})
</script>

Patrón de boundary de errores + Suspense

El patrón habitual en producción coloca Suspense dentro de un componente que actúa como boundary de errores. onErrorCaptured devuelve false para detener la propagación y mostrar una interfaz de error en su lugar.

<script setup>
import { ref, onErrorCaptured } from 'vue'
const err = ref(null)
onErrorCaptured((e) => { err.value = e; return false })
</script>

<template>
  <p v-if="err">Failed to load: {{ err.message }}</p>
  <Suspense v-else>
    <ProfilePanel />
    <template #fallback>Loading...</template>
  </Suspense>
</template>

Los eventos pending y resolve

Suspense emite eventos del ciclo de vida a los que puede suscribirse:

  • @pending — se emite al entrar en un estado pendiente (de carga)
  • @resolve — se emite cuando el slot default termina de resolverse
  • @fallback — se emite cuando se muestra el contenido fallback

Son útiles para análisis o barras de progreso.

<template>
  <Suspense @pending="onPending" @resolve="onResolve">
    <RouteView />
    <template #fallback>Loading route...</template>
  </Suspense>
</template>

Prop timeout para retrasar el fallback

El prop timeout (en milisegundos) retrasa la muestra del fallback. Si el trabajo asíncrono se resuelve antes de que transcurra el tiempo de espera, el fallback no aparece.

Esto evita que se muestre brevemente un spinner cuando las respuestas son rápidas.

<template>
  <!-- Only show fallback if loading exceeds 200ms -->
  <Suspense :timeout="200">
    <FastPanel />
    <template #fallback>Loading...</template>
  </Suspense>
</template>

Suspense con Router y transiciones

Suspense se combina con RouterView y Transition para animar los cambios de ruta asíncronos. El orden es importante: Transition envuelve a Suspense, que a su vez envuelve al componente de la ruta.

<template>
  <RouterView v-slot="{ Component }">
    <Transition mode="out-in">
      <Suspense>
        <component :is="Component" />
        <template #fallback>Loading page...</template>
      </Suspense>
    </Transition>
  </RouterView>
</template>

Cuándo NO usar Suspense

Evite Suspense para datos que se vuelven a solicitar con frecuencia mientras el componente permanece montado: solo controla la resolución asíncrona inicial. Para estados de carga continuos (paginación o nuevas solicitudes), use en su lugar un ref reactivo loading normal.

<script setup>
import { ref } from 'vue'
const loading = ref(false)
async function loadMore() {
  loading.value = true
  await fetchNextPage()
  loading.value = false
}
</script>

Comprobación rápida

Compruebe su comprensión de Suspense.

Recapitulación

Ha aprendido cómo Suspense coordina las dependencias asíncronas:

  • el slot default contiene contenido asíncrono (setup asíncrono o componentes asíncronos)
  • el slot fallback se muestra durante la carga
  • espera a que se resuelvan todos los hijos asíncronos antes de mostrar el contenido
  • los rechazos se propagan hasta onErrorCaptured en un boundary padre
  • timeout evita que el spinner aparezca brevemente; eventos como @resolve ayudan con los análisis

Preguntas frecuentes

¿La lección «Componente Vue Suspense» es gratis?

Sí — el texto completo de «Componente Vue Suspense» es gratis para leer aquí en la web. Para practicarla de forma interactiva (editor de código integrado y tutor de IA 24/7) y desbloquear el resto del curso de Vue Academy, actualiza a CoddyKit PRO. El curso de Vue Academy incluye 4 lecciones en total.

¿Qué aprenderé en «Componente Vue Suspense»?

con slots default y #fallback, carga de componentes asíncronos y Suspense anidado Practicas Vue Academy con código real que ejecutas directamente en el navegador, y un tutor de IA 24/7 responde tus preguntas mientras trabajas en la lección.

¿Necesito experiencia previa para empezar Vue Academy?

No se requiere experiencia previa. Vue Academy en CoddyKit está estructurado para principiantes hasta estudiantes avanzados, así que puedes empezar aquí o desde el inicio y avanzar a tu ritmo. Esta es la lección 1 de 4.

¿Cuánto tiempo toma la lección «Componente Vue Suspense»?

La mayoría de las lecciones de CoddyKit toman alrededor de 5–10 minutos. Cada una es compacta e interactiva, así que avanzas constantemente y retomas exactamente por donde dejaste en la web y la app.

¿Puedo escribir y ejecutar código en esta lección de Vue Academy?

Sí. Cada lección de Vue Academy incluye un editor de código integrado, así que escribes y ejecutas código real directamente en tu navegador y obtienes retroalimentación instantánea de IA — sin configuración local necesaria.

Todas las lecciones de este curso

  1. Componente Vue Suspense
  2. Componentes asíncronos con defineAsyncComponent
  3. SSR en streaming con renderToWebStream
  4. Estrategias de hidratación diferida
← Volver a Vue Academy