这一章进入 Nuxt 数据获取(Data Fetching),这也是 Nuxt 和 Vue 最大的区别之一。
讨论的核心不是 useFetch 怎么用,而是:
既然浏览器已经有 fetch(),Nuxt 为什么还要重新设计一个 useFetch()?
学习目标
理解为什么不能直接使用
fetch(),useFetch()解决了哪些问题,以及为什么它能配合 SSR 工作。
一、这个知识解决什么问题?
JavaScript 原生已经提供了 fetch('/api/user'),Vue 项目里也一直这样写。
那么 Nuxt 为什么还要重新设计 useFetch()?如果只是换了名字,那完全没有必要。所以:
useFetch 一定解决了 fetch 解决不了的问题。
二、一起推导
假设页面这样写:
const user = await fetch('/api/user')
根据前面几章我们已经知道:第一次访问页面时,服务器会执行这段代码,请求 /api/user(第一次)。
但是浏览器下载 JavaScript 后,组件还会执行一次。浏览器又执行了 fetch('/api/user')(第二次)。
同一个接口,请求了两次。
原生 fetch 最大的问题:
它不知道自己正运行在 Nuxt 的 SSR 生命周期里。
三、useFetch 做了什么?
Nuxt 在 fetch 外面包了一层,形成 useFetch(),除了请求接口,还做了四件事:
第一:支持 SSR
同一份代码,服务器和浏览器都能执行,不需要额外处理。
第二:支持 Payload
服务器请求到的数据,会被放进 Payload 一起发给浏览器。浏览器 Hydration 时直接读取,不再重复请求。
第三:自动管理状态
fetch() 需要自己管理 loading、error、data;useFetch() 直接提供:
const { data, pending, error } = useFetch(...)
第四:自动响应路由变化
当请求参数使用了响应式路由参数时,useFetch 可以监听依赖并重新获取数据。
四、fetch 与 useFetch 对比
| 能力 | fetch | useFetch |
|---|---|---|
| HTTP 请求 | ✅ | ✅ |
| SSR 支持 | ❌ 自己处理 | ✅ |
| Payload | ❌ | ✅ |
| 避免首次重复请求 | ❌ | ✅ |
| pending / error | ❌ | ✅ |
| 响应式 data | ❌ | ✅ |
| Nuxt 生命周期 | ❌ | ✅ |
更准确地说:
useFetch = fetch + SSR + Payload + 响应式 + 状态管理 + Nuxt 生命周期
五、脑图
读图时不要只比较"是否能发送 HTTP 请求",而要看完整生命周期:
- 原生
fetch只返回一次网络响应,不知道服务器数据应该如何交给 Hydration useFetch在服务端请求数据后,将结果以稳定 key 写入 Nuxt Payload- 客户端执行到同一个
useFetch时,先用 key 查找 Payload,命中后直接恢复响应式状态 - 后续刷新、响应式参数变化等场景,才会重新执行请求
六、容易踩坑
❌ useFetch 就是 fetch
不是。增加了 SSR、Payload、Cache、响应式、生命周期,已经完全不是一个层级。
❌ useFetch 不会执行两次
实际上 Server 和 Client 都会执行,但 Client 读取的是 Payload,所以不会重复请求网络。
❌ fetch 在 Nuxt 不能用
可以用,只是无法享受 SSR、Payload、Hydration 等配套能力。
一句话记忆
fetch 只会请求数据;useFetch 管理的是整个 Nuxt 数据获取生命周期。