Suspense
handle asynchronous components and improve user experience during loading.
Key concept
Async Components:
Suspense simplifies the handling of components that require asynchronous data or code loading.
Fallback Content:
You can define fallback content to be displayed while the asynchronous component is loading.
2 types of async dependencies that can wait on:
Components with an async setup() hook. This includes components using with top-level await expressions.
<script>
export default {
async setup() {
const res = await fetch(...)
const posts = await res.json()
return {
posts
}
}
}
</script>
Async components
suspensible by default: meaning that loading state will be automatically controlled by the "Suspense" component.
to opt-opt the suspense controlled, one can define "suspensible: false"
Slots:
The component has two slots: #default for regular content and #fallback for loading state content.
Only one immediate child node is allowed in each slot.
The content in the #default slot is displayed if possible; otherwise, the content in the #fallback slot is shown.
example:
<Suspense>
<!-- Component with nested async dependencies -->
<Dashboard />
<!-- Loading state via #fallback slot -->
<template #fallback>
Loading...
</template>
</Suspense>
Lifecycle:
On initial render, 'Suspense' renders its default slot content in memory.
If async dependencies are encountered, it enters a pending state, displaying the fallback content.
When all async dependencies are resolved, 'Suspense' enters a resolved state, showing the resolved default slot content.
If no async dependencies were encountered during initial render, 'Suspense' directly goes into a resolved state.
Reverting to Pending State:
'Suspense' reverts to a pending state only if the root node of the #default slot is replaced.
New async dependencies deeper in the tree won't trigger a revert to a pending state.
Revert Behavior:
When a revert happens, fallback content is not immediately displayed.
'Suspense' shows the previous #default content while waiting for the new content and its async dependencies to be resolved.
The timeout prop can be used to configure the revert behavior. If rendering the new content takes longer than the specified timeout, 'Suspense' switches to fallback content.
A timeout value of 0 displays the fallback content immediately when default content is replaced.
Suspense events
Pending Event:
Event Name: pending
Description: Occurs when the component enters a pending state. This typically happens when there are asynchronous dependencies being resolved.
Usage: display a loading indicator
Resolve Event:
Event Name: resolve
Description: Emitted when new content in the default slot has finished resolving. This event signifies that the asynchronous dependencies have been successfully resolved.
Usage: handle the successful resolution of asynchronous dependencies
Fallback Event:
Event Name: fallback
Description: Fired when the contents of the fallback slot are shown. This event is triggered when the component enters a pending state, and the fallback content is displayed.
Usage: perform actions when fallback content is shown
Error handling
'Suspense' itself does not provide built-in error handling for asynchronous operations.
use 'errorCaptured' or 'onErrorCaptured()' hook for error handling
Combining with other components
the nesting order of components is important !!!!
Components Combination Example
Components Used:
'RouterView': Vue Router's component for displaying matched components.
'Transition': Vue's transition component for handling transitions between components.
'KeepAlive': Vue's component for caching and keeping alive components.
'Suspense': Vue's component for handling loading states during asynchronous
<RouterView v-slot="{ Component }">
<template v-if="Component">
<Transition mode="out-in">
<KeepAlive>
<Suspense>
<!-- Main Content -->
<component :is="Component"></component>
<!-- Loading State -->
<template #fallback>
Loading...
</template>
</Suspense>
</KeepAlive>
</Transition>
</template>
</RouterView>
Nesting Order:
'RouterView' is used to display the matched component.
Inside 'RouterView', there is a check for the existence of the component ('template v-if="Component"') before applying transitions.
'Transition' is used to manage the transition effect between components (mode="out-in").
'KeepAlive' is employed to cache and keep alive components, preserving their state.
'Suspense' wraps the main content and provides a loading state using the #fallback slot.
Last updated