Nuxt4 数据获取
数据获取是 Nuxt 开发的核心,Nuxt 提供了 useFetch 和 useAsyncData 两个核心 composable,它们能在服务端和客户端都正确工作,并且保证数据一致。
useFetch
useFetch 是最常用的数据获取方式,用法简单:
<script setup>
const { data, pending, error, refresh } = await useFetch('https://jsonplaceholder.typicode.com/users')
</script>
<template>
<div v-if="pending">加载中...</div>
<div v-else-if="error">加载失败:{{ error.message }}</div>
<ul v-else>
<li v-for="user in data" :key="user.id">{{ user.name }}</li>
</ul>
</template>
其中 https://jsonplaceholder.typicode.com/users 是外部 API 地址,也可以是站内路径(如 /api/users),站内路径对应 server/ 目录中的接口,详见服务端接口。
返回值说明
| 返回值 | 类型 | 作用 |
|---|---|---|
data |
Ref | 请求返回的数据,成功后可用 |
pending |
Ref<boolean> | 是否正在请求,用于显示加载状态 |
error |
Ref | 请求出错时的错误对象 |
refresh |
函数 | 手动重新发起请求 |
status |
Ref | 请求状态,idle、pending、success、error |
在模板中 data、pending 等变量会自动解包,不需要写 .value。
useAsyncData 与 $fetch
useFetch 是 useAsyncData 加 $fetch 的组合,当需要获取数据前先做处理,比如调用函数、请求时传 token,就用 useAsyncData:
<script setup>
const { data } = await useAsyncData('users', () => {
// 这里可以做任何异步操作
return $fetch('https://jsonplaceholder.typicode.com/users', {
headers: { Authorization: 'Bearer xxx' }
})
})
</script>
区别在于 useFetch 直接传入 URL,useAsyncData 需要自己写一个返回数据的函数,且第一个参数是数据 key。
双端执行与数据同步
这是 Nuxt 数据获取和普通 Vue 项目最大的不同。
在服务端渲染(SSR)模式下,useFetch 会在服务器上执行一次请求,用返回的数据渲染 HTML 发给浏览器。浏览器端 hydration 时,Nuxt 不会重复请求,而是直接复用服务端的数据,保证两端数据一致。
这就是为什么 SSR 页面首屏快而且没有闪烁,数据在 HTML 里就有了。同时 data 是响应式的,客户端后续也可以调用 refresh() 刷新数据。
数据共享与自动清理
Nuxt 4 的数据层有两个重要的自动行为:
第一,相同 key 自动共享。 useAsyncData 或 useFetch 传入相同 key 时,多个组件会共享同一份数据,不会重复请求:
<script setup>
// 页面 A 和页面 B 都用这个 key,只会请求一次
const { data } = await useAsyncData('users', () => $fetch('https://jsonplaceholder.typicode.com/users'))
</script>
第二,卸载自动清理。 组件卸载时,Nuxt 会自动清理不再使用的数据,无需手动处理,避免内存泄漏。
响应式 key
key 可以是响应式的。当 key 变化时,数据会自动重新获取:
<script setup>
const route = useRoute()
const id = computed(() => route.params.id)
// URL 随 id 变化,id 变化时自动重新请求
const { data: user } = await useFetch(() => `https://jsonplaceholder.typicode.com/users/${id.value}`)
</script>
注意 URL 要用函数(或 ref)写法,Nuxt 会监听其依赖自动重新请求。直接写模板字符串 \/api/users/${id.value}`` 只会请求一次,不会随 id 更新。
提示:useFetch 的自动生成 key 是基于调用位置的。多个不同组件里用相同 URL 调用 useFetch,默认不会共享数据。需要跨组件共享时,用 useAsyncData 并显式传入相同 key。
useFetch 与 fetch 的区别
| 对比 | fetch / $fetch |
useFetch |
|---|---|---|
| 服务端渲染 | 只在发起请求的那一端执行 | 服务端执行并同步到客户端 |
| 状态管理 | 无,自己管理 | 内置 data、pending、error 状态 |
| 数据缓存 | 无 | 按 key 去重共享 |
| 使用场景 | 事件回调、一次性请求、API 测试 | 页面初始化、需要响应式的数据 |
一句话总结:useFetch 是 Nuxt 数据获取的第一选择,服务端自动执行、双端数据一致、按 key 去重共享。