译零 TransZero · TanStack Query 中文文档
主站

Suspense(实验性功能)

更新于 2026-11-02 Vue 查看英文原文 ↗

注意:Vue Query 的 Suspense 模式属于实验性功能,与 Vue 自身的 Suspense 一样。这些 API 将发生变更,除非你将 Vue 和 Vue Query 的版本均锁定在相互兼容的补丁级版本,否则不应在生产环境中使用。

Vue Query 也可与 Vue 新的 Suspense API 配合使用。

为此,你需要用 Vue 提供的 Suspense 组件包裹可挂起(suspendable)组件:

HTML
1<script setup>2import SuspendableComponent from './SuspendableComponent.vue'3</script>4 5<template>6  <Suspense>7    <template #default>8      <SuspendableComponent />9    </template>10    <template #fallback>11      <div>Loading...</div>12    </template>13  </Suspense>14</template>

并将可挂起组件中的 setup 函数改为 async。随后即可使用 vue-query 提供的异步 suspense 函数(useQuery 和 useInfiniteQuery 均返回该函数):

HTML
1<script>2import { defineComponent } from 'vue'3import { useQuery } from '@tanstack/vue-query'45const todoFetcher = async () =>6  await fetch('https://jsonplaceholder.cypress.io/todos').then((response) =>7    response.json(),8  )9export default defineComponent({10  name: 'SuspendableComponent',11  async setup() {12    const { data, suspense } = useQuery({13      queryKey: ['todos'],14      queryFn: todoFetcher,15    })16    await suspense()1718    return { data }19  },20})21</script>

suspense() 的解析逻辑

  • 若查询尚无数据,或其数据已过期,则会拉取该查询,并在拉取完成时以结果解析。这通常发生在查询函数执行完毕时,但也可能更早,例如在 experimental_streamedQuery 返回首个数据块后,或在拉取进行中由 setQueryData 设置了数据时。
  • 若数据为新鲜状态,则立即解析,不重新拉取。
  • 当查询被禁用(enabled: false)时,它会等待查询启用后再解析;因此,若查询始终处于禁用状态,则永远不会解析。在服务端,这会阻塞渲染,请参阅 SSR。
  • 若拉取失败,则以错误状态的查询结果解析。仅当 throwOnError 为(或返回)true 时,它才会以错误拒绝。

错误处理

由于 suspense() 默认以错误结果解析,因此拉取失败后组件仍会渲染,并可从查询中读取 error。若希望由父组件统一处理错误,请设置 throwOnError: true。此时 suspense() 将以错误拒绝,错误将从 async setup 中向外抛出,你可在 Suspense 的父组件中使用 onErrorCaptured 捕获该错误:

HTML
1<script setup>2import { onErrorCaptured, ref } from 'vue'3import SuspendableComponent from './SuspendableComponent.vue'45const error = ref(null)67onErrorCaptured((err) => {8  error.value = err9  return false10})11</script>12 13<template>14  <div v-if="error">Something went wrong: {{ error.message }}</div>15  <Suspense v-else>16    <template #default>17      <SuspendableComponent />18    </template>19    <template #fallback>20      <div>Loading...</div>21    </template>22  </Suspense>23</template>

拉取时渲染 vs 边渲染边拉取

开箱即用情况下,Vue Query 在 suspense 模式下天然适配 拉取时渲染(Fetch-on-render) 方案,无需额外配置。这意味着:当你的组件尝试挂载时,会触发查询拉取并挂起,但仅在你导入并挂载这些组件之后才发生。若你想进阶采用 边渲染边拉取(Render-as-you-fetch) 模型,我们建议在路由回调和/或用户交互事件中实现 Prefetching,以便在组件挂载前、甚至在其父组件导入或挂载之前就启动查询加载。

本页为 TanStack Query 文档(Vue 版)的非官方中文翻译,原文由上游团队维护,遵循 MIT 许可。 译文如有偏差,以英文原文为准。

译自上游 59d11de