useFetch 与 useAsyncData
使用 useFetch 和 useAsyncData 获取服务器端数据,处理等待和错误状态,并了解 Nuxt 如何对客户端进行水合。
useFetch 与 useAsyncData 是 CoddyKit 上的免费 Frontend Academy 课时。 这是第 2 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Frontend Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Frontend Academy 课程共包含 4 节课。
Nuxt 3 中的数据获取
Nuxt 提供两个主要的组合式函数来获取数据:useFetch(基于 URL,在底层调用 fetch)和 useAsyncData(可接受任意异步函数,并使用唯一键进行缓存和去重)。
useFetch——快速方式
传入 URL 后,Nuxt 会在 SSR 期间获取数据,在客户端进行激活,并防止客户端在激活期间重复获取数据。
<script setup>
const { data: posts, pending, error } = await useFetch('/api/posts');
</script>
<template>
<div v-if="pending">Loading...</div>
<div v-else-if="error">{{ error.message }}</div>
<ul v-else>
<li v-for="p in posts" :key="p.id">{{ p.title }}</li>
</ul>
</template>为什么激活时不会重复获取数据
Nuxt 会将获取的数据序列化到 SSR HTML 载荷中。在客户端,useFetch 会从该载荷中激活数据,因此不会发起第二次网络请求。这是 SSR 优化的关键。
useAsyncData——灵活的异步方式
当数据获取并非简单的 URL 请求时使用它,例如数据库查询、自定义逻辑或多步骤请求。
<script setup>
const { data: user } = await useAsyncData('user-profile', async () => {
const me = await $fetch('/api/me');
const stats = await $fetch(`/api/users/${me.id}/stats`);
return { ...me, stats };
});
</script>缓存键很重要
useAsyncData 的第一个参数是唯一的缓存键。在多个组件之间共享相同的键时,系统会对请求去重并复用结果。不同的键表示独立的获取操作。
// Two components calling useFetch('/api/posts') share one request
// Two components calling useFetch('/api/posts', { key: 'a' }) and { key: 'b' } fetch twice刷新与延迟加载
两个组合式函数都会返回 refresh() 以重新获取数据,并接受 { lazy: true } 以跳过阻塞 SSR(数据会在页面渲染后加载)。
const { data, refresh } = await useFetch('/api/posts');
async function onSave() {
await $fetch('/api/posts', { method: 'POST', body: newPost });
await refresh();
}
// Or lazy mode:
const { data, pending } = useFetch('/api/posts', { lazy: true });监听与响应式 URL
为 URL 传入一个函数——它具有响应性。当依赖项发生变化时,会重新获取数据。
<script setup>
const page = ref(1);
const { data } = await useFetch(() => `/api/posts?page=${page.value}`);
// Changing page.value re-runs the fetch
</script>请求选项
useFetch 接受与 fetch 相同的选项——method、body、headers,以及 default 和 transform 等 Nuxt 专用选项。
const { data } = await useFetch('/api/posts', {
method: 'POST',
body: { title: 'Hello' },
headers: { 'X-Custom': '1' },
transform: (raw) => raw.items.map(transformItem),
default: () => []
});$fetch——命令式获取
$fetch 是 Nuxt 的通用获取器(底层使用 ofetch)。它不会自动跟踪激活状态。请在事件处理程序和数据变更中使用它。
async function deletePost(id) {
await $fetch(`/api/posts/${id}`, { method: 'DELETE' });
await refresh();
}错误处理
在获取处理程序中抛出错误即可显示该错误。页面可以使用 ~/error.vue 显示自定义错误页面。
// error.vue at project root
<script setup>
const props = defineProps<{ error: any }>();
</script>
<template>
<div>
<h1>{{ error.statusCode }}</h1>
<p>{{ error.message }}</p>
<button @click="clearError({ redirect: '/' })">Home</button>
</div>
</template>身份验证与 Cookie
useFetch 会在 SSR 期间自动转发 Cookie,因此经过身份验证的请求在服务器和客户端上都能正常工作,无需手动处理 Cookie。
useFetch 与 useAsyncData——何时使用
useFetch:简单的基于 URL 的请求(占 95% 的情况)。useAsyncData:自定义异步逻辑、多步骤组合以及非 URL 数据源(例如通过 server/utils 访问数据库)。
快速检查
为什么 Nuxt 3 中的 useFetch 可以防止页面在客户端激活时发起重复的网络请求?
回顾:useFetch 与 useAsyncData
useFetch:适用于基于 URL 的场景,占 95%。useAsyncData:适用于带有唯一缓存键的自定义异步逻辑。两者都会从 SSR 载荷中进行水合(不会重复请求)。使用 refresh() 重新获取数据,使用 lazy:true 跳过会阻塞 SSR 的请求。响应式 URL 会触发重新获取。使用 $fetch 执行命令式变更。error.vue 负责处理错误。SSR 期间会自动转发 Cookie。
常见问题解答
「useFetch 与 useAsyncData」课时是免费的吗?
是的 — 「useFetch 与 useAsyncData」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Frontend Academy 课程的其余内容,请升级到 CoddyKit PRO。 Frontend Academy 课程共包含 4 节课。
「useFetch 与 useAsyncData」这节课中我会学到什么?
使用 useFetch 和 useAsyncData 获取服务器端数据,处理等待和错误状态,并了解 Nuxt 如何对客户端进行水合。 你通过在浏览器中直接运行的动手代码来练习 Frontend Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。
学习 Frontend Academy 需要有经验吗?
无需任何先前经验。CoddyKit 上的 Frontend Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 2 节课,共 4 节。
「useFetch 与 useAsyncData」课时需要多长时间?
大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。
我能在这节 Frontend Academy 课中编写并运行代码吗?
能。每节 Frontend Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。
此课程中的所有课时
- 基于文件的路由与自动导入
- useFetch 与 useAsyncData
- Nuxt 模块:图像、身份验证与国际化
- 部署:静态模式与 SSR