useFetch()
当 Endpoint 不在缓存中或已过时时获取它。返回一个持有获取 promise(带有 resolved 标志)的
Ref。当参数变化或数据失效时,会触发新的获取。用它来提前发起获取,然后再用
useSuspense()、useCache() 或 useDLE() 读取数据。
用法
并行加载数据
在 <script setup> 中,await useSuspense() 是顺序执行的。先为每个 endpoint 调用 useFetch(),就能并行发起所有获取;随后的 useSuspense() 调用会复用这些进行中的请求。
Resources
PostWithComments.vue
<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>
行为
| 过期状态 | 获取 | .value | resolved | 条件 |
|---|---|---|---|---|
| Invalid | 是1 | pending 状态的 promise | false | 不在 store 中、删除、失效 |
| Stale | 是1 | pending 状态的 promise | false | (首次渲染、参数变化)且 过期时间 < 当前时间 |
| Valid | 否 | 已 resolve 的 promise | true | 获取完成 |
| Error | 否 | 已 reject 的 promise | true | 获取失败 |
| 否 | undefined | 第二个参数为 null |
每当触发获取时,返回的 Ref 都会更新为新的 promise:包括参数变化、失效或重置时。
备注
- 相同的获取会自动去重
条件依赖
将 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>