You've probably written lots of components that handle their own loading state.
Either while data is being fetched or while an async component is loaded.
But with the new Suspense
component, we can instead handle that loading state further up the component tree:
<template><Suspense><!-- Shown once ChatWindow loads --><template #default><ChatWindow /></template><!-- Loading state --><template #fallback><Spinner color="blue" /></template></Suspense></template>
<script setup>import { defineAsyncComponent } from "vue";import Spinner from "@/components/Spinner.vue";// ChatWindow will load asynchronously, but it doesn't// have to have any loading state at all. Or even know// that it's being loaded asynchronously!const ChatWindow = defineAsyncComponent(() => import("@/components/ChatWindow"));</script>
This also works if the child component returns a Promise from the setup
function:
// async functions always return a Promiseasync setup() {const { users } = await loadData();return {users,};}
Even better is that the async child component can be anywhere as a descendant.
This means you can have a "root" loading state in your app, and any async components anywhere will trigger this loading state:
<!-- App.vue --><template><Suspense><template #default><AppWithAsyncBehaviour /></template><template #fallback><FullPageLoading /></template></Suspense></template>