Ionic 视图中的 Vue 悬念
Vue Suspense in Ionic view
我有这样的看法:
<template>
<ion-page>
<ion-router-outlet></ion-router-outlet>
<suspense>
<template #default>
{{ pages }}
</template>
<template #fallback>
<div>Loading...</div>
</template>
</suspense>
</ion-page>
</template>
...
async setup() {
const storageRef = storage.ref();
const bookRef = storageRef.child("content/books/bk0000001");
const pages = await bookRef.listAll();
console.log({ pages }); // is logged correctly
return { pages }
}
虽然它似乎可以很好地加载内容,但没有呈现模板,页面仍然是空的,default
和 fallback
内容都没有显示。
我做错了什么?
当组件的 setup()
为 async
时,组件必须在组件的父级 中的 <suspense>
内(不是在组件本身中)。
您应该将 {{ pages }}
标记和从 async setup()
获取的数据移动到它自己的组件中:
<!-- AsyncPages.vue -->
<template>
<ul>
<li v-for="page in pages" :key="page.id">{{ page.title }}</li>
</ul>
</template>
<script>
import { defineComponent } from 'vue'
export default defineComponent({
async setup() {
const resp = await fetch('https://jsonplaceholder.typicode.com/posts')
const pages = await resp.json()
return { pages }
}
})
</script>
并更新父组件以在 <suspense>
:
中使用新组件
<!-- Parent.vue -->
<template>
<ion-page>
<ion-router-outlet></ion-router-outlet>
<suspense>
<template #default>
<AsyncPages />
</template>
<template #fallback>
<div>Loading...</div>
</template>
</suspense>
</ion-page>
</template>
<script>
import { defineComponent } from 'vue'
import AsyncPages from '@/components/AsyncPages.vue'
export default defineComponent({
components: {
AsyncPages
}
})
</script>
或者,您可以使用 onMounted
异步挂钩将上面的代码重写为非异步 setup()
:
<!-- Parent.vue -->
<template>
<ion-page>
<ion-router-outlet></ion-router-outlet>
<ul v-if="pages">
<li v-for="page in pages" :key="page.id">{{ page.title }}</li>
</ul>
<div v-else>Loading...</div>
</ion-page>
</template>
<script>
import { defineComponent, onMounted, ref } from 'vue'
export default defineComponent({
setup() {
const pages = ref(null)
onMounted(async () => {
const resp = await fetch('https://jsonplaceholder.typicode.com/posts')
pages.value = await resp.json()
})
return { pages }
}
})
</script>
我有这样的看法:
<template>
<ion-page>
<ion-router-outlet></ion-router-outlet>
<suspense>
<template #default>
{{ pages }}
</template>
<template #fallback>
<div>Loading...</div>
</template>
</suspense>
</ion-page>
</template>
...
async setup() {
const storageRef = storage.ref();
const bookRef = storageRef.child("content/books/bk0000001");
const pages = await bookRef.listAll();
console.log({ pages }); // is logged correctly
return { pages }
}
虽然它似乎可以很好地加载内容,但没有呈现模板,页面仍然是空的,default
和 fallback
内容都没有显示。
我做错了什么?
当组件的 setup()
为 async
时,组件必须在组件的父级 中的 <suspense>
内(不是在组件本身中)。
您应该将 {{ pages }}
标记和从 async setup()
获取的数据移动到它自己的组件中:
<!-- AsyncPages.vue -->
<template>
<ul>
<li v-for="page in pages" :key="page.id">{{ page.title }}</li>
</ul>
</template>
<script>
import { defineComponent } from 'vue'
export default defineComponent({
async setup() {
const resp = await fetch('https://jsonplaceholder.typicode.com/posts')
const pages = await resp.json()
return { pages }
}
})
</script>
并更新父组件以在 <suspense>
:
<!-- Parent.vue -->
<template>
<ion-page>
<ion-router-outlet></ion-router-outlet>
<suspense>
<template #default>
<AsyncPages />
</template>
<template #fallback>
<div>Loading...</div>
</template>
</suspense>
</ion-page>
</template>
<script>
import { defineComponent } from 'vue'
import AsyncPages from '@/components/AsyncPages.vue'
export default defineComponent({
components: {
AsyncPages
}
})
</script>
或者,您可以使用 onMounted
异步挂钩将上面的代码重写为非异步 setup()
:
<!-- Parent.vue -->
<template>
<ion-page>
<ion-router-outlet></ion-router-outlet>
<ul v-if="pages">
<li v-for="page in pages" :key="page.id">{{ page.title }}</li>
</ul>
<div v-else>Loading...</div>
</ion-page>
</template>
<script>
import { defineComponent, onMounted, ref } from 'vue'
export default defineComponent({
setup() {
const pages = ref(null)
onMounted(async () => {
const resp = await fetch('https://jsonplaceholder.typicode.com/posts')
pages.value = await resp.json()
})
return { pages }
}
})
</script>