Suspense (实验性)

注意:Vue Query 的 Suspense 模式是实验性的,与 Vue 本身的 Suspense 一样。这些 API 将会改变,除非您将 Vue 和 Vue Query 的版本锁定到相互兼容的补丁级别版本,否则不应在生产环境中使用。

Vue Query 也可以与 Vue 的新 Suspense API 一起使用。

为此,您需要用 Vue 提供的 Suspense 组件包裹您的可挂起组件。

vue
<script setup>
import SuspendableComponent from './SuspendableComponent.vue'
</script>

<template>
  <Suspense>
    <template #default>
      <SuspendableComponent />
    </template>
    <template #fallback>
      <div>Loading...</div>
    </template>
  </Suspense>
</template>
<script setup>
import SuspendableComponent from './SuspendableComponent.vue'
</script>

<template>
  <Suspense>
    <template #default>
      <SuspendableComponent />
    </template>
    <template #fallback>
      <div>Loading...</div>
    </template>
  </Suspense>
</template>

然后,将可挂起组件中的 setup 函数更改为 async。之后,您就可以使用 vue-query 提供的异步 suspense 函数。

vue
<script>
import { defineComponent } from 'vue'
import { useQuery } from '@tanstack/vue-query'

const todoFetcher = async () =>
  await fetch('https://jsonplaceholder.cypress.io/todos').then((response) =>
    response.json(),
  )
export default defineComponent({
  name: 'SuspendableComponent',
  async setup() {
    const { data, suspense } = useQuery(['todos'], todoFetcher)
    await suspense()

    return { data }
  },
})
</script>
<script>
import { defineComponent } from 'vue'
import { useQuery } from '@tanstack/vue-query'

const todoFetcher = async () =>
  await fetch('https://jsonplaceholder.cypress.io/todos').then((response) =>
    response.json(),
  )
export default defineComponent({
  name: 'SuspendableComponent',
  async setup() {
    const { data, suspense } = useQuery(['todos'], todoFetcher)
    await suspense()

    return { data }
  },
})
</script>

渲染时获取 vs 渲染即获取

开箱即用,Vue Query 的 suspense 模式作为一个 **渲染时获取 (Fetch-on-render)** 解决方案表现得非常好,无需额外配置。这意味着当您的组件尝试挂载时,它们将触发查询获取并挂起,但这仅在您导入并挂载了它们之后。如果您想更进一步,实现 **边获取边渲染 (Render-as-you-fetch)** 模型,我们建议在路由回调和/或用户交互事件上实现 预取 (Prefetching),以便在查询挂载之前甚至在父组件开始导入或挂载之前就开始加载查询。