Suspense
- Published
- Tags
- #notes#vue#web dev
Parent Component
html
<script setup lang="ts">
import TestView from '~/views/TestView.vue'
import TestView2 from '~/views/TestView2.vue'
const view = $ref(1)
let error = $ref<string | undefined>()
onErrorCaptured(() => {
error = 'Sorry something is horribly wrong.... blame the devs'
})
const pending = () => console.log('pending')
const fallback = () => console.log('fallback')
const resolve = () => console.log('resolve')
</script>
<template>
<BButton @click="view = 2">
Update
</BButton>
<!-- Timeout 0 Forces fallback when component switching -->
<div class="column">
<Suspense
:timeout="0"
@pending="pending"
@fallback="fallback"
@resolve="resolve"
>
<template #default>
<component :is="view === 1 ? TestView : TestView2" />
</template>
<template #fallback>
<p v-if="error">
{{ error }}
</p>
<div
v-else
class="row justify-center"
>
<p class="column">
<CircleSpinner />
<EllipsisSpinner />
</p>
</div>
</template>
</Suspense>
</div>
</template>
Child Component
html
<script setup lang="ts">
interface Movie {
img: string
title: string
description: string
}
let movie = $ref<Movie>({
img: '',
title: '',
description: '',
})
async function getMovie() {
await new Promise((resolve) => setTimeout(resolve, 3000))
movie = {
img: 'words',
title: 'ah',
description: 'okay',
}
}
await getMovie()
</script>
<template>
<p>Image: {{ movie.img }}</p>
<p>Title: {{ movie.title }}</p>
<p>Description: {{ movie.description }}</p>
</template>
<style lang="scss" scoped>
</style>