Componente Suspense
Suspense es un componente integrado introducido en Vue 3.2, funcionalmente similar al componente React.Suspense. Este componente ofrece dos ranuras (slots): default y fallbackLa ranura default contiene componentes con dependencias asíncronas porfundas o componentes asíncronos Minetras el componente en la ranura default no alcance el estado fulfilled (completado sin excepciones), se mostrará el contenido de la ranura fallback
1. Combinación con defineAsyncComponent para carga diferida de componentes
componente hijo A
<!-- ./components/A.vue -->
<template>
<h1>¡Hola mundo!</h1>
</template>
componente padre
<script setup lang="ts">
import {defineAsyncComponent} from "vue";
const MiComponenteDiferido = defineAsyncComponent(() => import('./components/A.vue'))
</script>
<template>
<Suspense>
<MiComponenteDiferido/>
<template #fallback>
<p>Cargando contenido...</p>
</template>
</Suspense>
</template>
2. Utilización de setup asíncrono
componente hijo B
<!-- ./components/B.vue -->
<script lang="ts" setup>
const obtenerContenido = () => {
return new Promise<string>((resolver, rechazar) => {
setTimeout(() => {
resolver('¡Bienvenido!')
// rechazar(new Error('Error en la carga'))
}, 2000)
})
}
// Uso de await en nivel superior en script setup, Vue convierte setup en una función asíncrona
const contenido = await obtenerContenido()
</script>
<template>
<h1>{{contenido}}</h1>
</template>
componente padre
<script setup lang="ts">
import ComponenteConContenido from './components/B.vue'
</script>
<template>
<Suspense>
<ComponenteConContenido/>
<template #fallback>
<p>Procesando solicitud...</p>
</template>
</Suspense>
</template>
3. Integración con vueRouter
<RouterView v-slot="{ Componente }">
<template v-if="Componente">
<Transition mode="out-in">
<KeepAlive>
<Suspense>
<!-- Contenido principal -->
<component :is="Componente"></component>
<!-- Estado de carga -->
<template #fallback>
Cargando recursos...
</template>
</Suspense>
</KeepAlive>
</Transition>
</template>
</RouterView>
4. Manejo de errores
El componente
<Suspense>por sí mismo no proporciona manejo de errores actualmente. Sin embargo, es posible utilizar la opciónerrorCapturedo el ganchoonErrorCaptured()en el componente padre que utiliza<Suspense>para capturar y manejar errores asíncronos.
Usando el componente B como ejemplo, modificamos obtenerContenido para que rechace en lugar de resolver
- resolver('¡Bienvenido!')
+ rechazar(new Error('Fallo en la operación'))
componente padre
<script setup lang="ts">
import {defineAsyncComponent, onErrorCaptured, ref} from "vue";
const ComponenteConError = defineAsyncComponent(() => import('./components/B.vue'))
const mensajeError = ref<string | null>(null)
onErrorCaptured((error) => {
mensajeError.value = error instanceof Error ? error.message : (error || 'Ocurrió un error')
})
</script>
<template>
<Suspense>
<ComponenteConError/>
<template #fallback>
<p>{{ mensajeError || 'Cargando información...' }}</p>
</template>
</Suspense>
</template>