跳到主要内容

useFetch()

当 Endpoint 不在缓存中或已过时时获取它。返回一个持有获取 promise(带有 resolved 标志)的 Ref。当参数变化或数据失效时,会触发新的获取。用它来提前发起获取,然后再用 useSuspense()、useCache() 或 useDLE() 读取数据。

用法​

并行加载数据​

在 <script setup> 中,await useSuspense() 是顺序执行的。先为每个 endpoint 调用 useFetch(),就能并行发起所有获取;随后的 useSuspense() 调用会复用这些进行中的请求。

<script setup lang="ts">
  import { useFetch, useSuspense } from '@data-client/vue';
  import { PostResource, CommentResource } from './Resources';

  const props = defineProps<{ id: number }>();

  // Both fetches start in parallel
  useFetch(PostResource.get, () => ({ id: props.id }));
  useFetch(CommentResource.getList, () => ({ postId: props.id }));

  // useSuspense() reads the results — the second fetch
  // is already in-flight while the first one is awaited
  const post = await useSuspense(PostResource.get, () => ({ id: props.id }));
  const comments = await useSuspense(CommentResource.getList, () => ({
    postId: props.id,
  }));
</script>

<template>
  <article>
    <h3>{{ post.title }}</h3>
    <p>{{ post.body }}</p>
    <h4>Comments</h4>
    <div v-for="comment in comments" :key="comment.id" class="listItem">
      <strong>{{ comment.author }}</strong>: {{ comment.text }}
    </div>
  </article>
</template>

预取​

useFetch() 也可以单独使用,在渲染树的较早位置确保资源在需要之前就已可用。

提示

在另一个组件中与数据绑定 hook(useCache()、useSuspense()、useDLE()、useLive())结合使用。

MasterPost.vue
<script setup lang="ts">
import { useFetch } from '@data-client/vue';
import { PostResource } from './Resources';

const props = defineProps<{ id: number }>();
useFetch(PostResource.get, () => ({ id: props.id }));
// ...
</script>

行为​

过期状态获取.valueresolved条件
Invalid是1pending 状态的 promisefalse不在 store 中、删除、失效
Stale是1pending 状态的 promisefalse(首次渲染、参数变化)且 过期时间 < 当前时间
Valid否已 resolve 的 promisetrue获取完成
Error否已 reject 的 promisetrue获取失败
否undefined第二个参数为 null

每当触发获取时,返回的 Ref 都会更新为新的 promise:包括参数变化、失效或重置时。

备注
  1. 相同的获取会自动去重
条件依赖

将 null 作为任意 Data Client hook 的第二个参数,表示“什么都不做”。

// todo could be undefined if id is undefined
const todo = useFetch(
TodoResource.get,
computed(() => (id.value ? { id: id.value } : null)),
);

类型​

function useFetch(
endpoint: ReadEndpoint,
...args: MaybeRefsOrGetters<Parameters<typeof endpoint>> | [null]
): Readonly<
Ref<
| (Promise<Denormalize<typeof endpoint.schema>> & {
resolved: boolean;
})
| undefined
>
>;

参数可以是普通值、refs(包括 computed),或者像 () => ({ id: props.id }) 这样的 getter 函数。像 { id: props.id } 这样的普通对象只会被读取一次,不会跟随 prop 或路由的变化,因此当参数可能变化时,请使用 getter 或 computed。

参数变化时会触发新的获取。

示例​

检查获取状态​

使用 promise.resolved 检查数据是否仍在加载:

MasterPost.vue
<script setup lang="ts">
import { useFetch } from '@data-client/vue';
import { PostResource } from './Resources';

const props = defineProps<{ id: number }>();
const promise = useFetch(PostResource.get, () => ({ id: props.id }));
if (promise.value && !promise.value.resolved) {
// fetch is in-flight
}
// ...
</script>