Nuxt3中useFetch与useAsyncData的正确使用姿势
深入解析Nuxt3中useFetch与useAsyncData的核心区别与最佳实践,涵盖SSR服务端渲染、响应式依赖监听、缓存策略管理等关键知识点,帮助开发者避开常见陷阱,提升前端开发效率与页面性能。
## 前言
在 Nuxt3 项目开发中,数据获取是最常见的操作之一。很多开发者在使用 `useFetch` 和 `useAsyncData` 时容易踩坑,导致页面渲染异常或性能问题。本文结合实际项目经验,总结这两个组合式函数的正确使用方式和常见误区。
## useFetch 与 useAsyncData 的区别
### useFetch 的本质
`useFetch` 实际上是 `useAsyncData` 的一个便捷封装,它自动生成唯一的 key 并处理响应式数据。源码层面,useFetch 内部调用了 useAsyncData:
```typescript
// 简化的实现逻辑
export const useFetch = (url, options) => {
return useAsyncData(
options.key || JSON.stringify([url, options]),
() => $fetch(url, options),
options
)
}
```
### useAsyncData 更灵活
当你需要自定义缓存 key、处理复杂的数据转换逻辑,或同时管理多个相关请求时,`useAsyncData` 更合适:
```typescript
// 自定义 key,便于手动刷新或失效缓存
const { data, refresh } = await useAsyncData('user-profile', () =>
$fetch('/api/user/profile')
)
```
## 常见误区与解决方案
### 误区一:在事件处理函数中直接使用
```typescript
// 错误示例
const handleClick = async () => {
const { data } = await useFetch('/api/data')
}
```
问题:useFetch/useAsyncData 必须在 setup 函数或组件顶层调用,不能在事件处理函数中使用。
解决方案:
```typescript
// 正确做法:使用 $fetch 或提前声明
const { data, refresh } = await useFetch('/api/data')
const handleClick = () => {
refresh() // 刷新数据
}
```
### 误区二:响应式依赖变化时不重新请求
```typescript
// 错误示例:filter 变化时不会重新请求
const filter = ref('all')
const { data } = await useFetch('/api/articles')
```
解决方案:使用 watch 或 computedKey:
```typescript
// 方案一:watch 选项
const filter = ref('all')
const { data } = await useFetch('/api/articles', {
query: { filter },
watch: [filter] // filter 变化时自动重新请求
})
// 方案二:响应式 key
const { data } = await useAsyncData(
computed(() => `articles-${filter.value}`),
() => $fetch('/api/articles', { query: { filter: filter.value } })
)
```
### 误区三:忽略 SSR 与 CSR 的差异
在服务端渲染时,useFetch 会执行并缓存结果。但如果客户端再次执行相同请求,可能导致数据不一致。
```typescript
// 最佳实践:明确指定 server 选项
const { data } = await useFetch('/api/user-info', {
server: false, // 仅客户端请求
lazy: true, // 非阻塞式加载
})
```
## 性能优化建议
### 合理使用 lazy 选项
对于非首屏关键数据,使用 `lazy: true` 避免阻塞页面渲染:
```typescript
const { data } = await useFetch('/api/recommendations', {
lazy: true,
default: () => [] // 提供默认值避免 undefined 错误
})
```
### 缓存策略
Nuxt3 默认缓存相同 key 的请求结果。手动控制缓存:
```typescript
// 获取刷新函数
const { data, refresh, clear } = await useAsyncData('cached-data', fetcher)
// 主动刷新
refresh()
// 清除缓存
clearNuxtData('cached-data')
```
## 总结
1. 优先使用 `useFetch`,复杂场景下用 `useAsyncData`
2. 始终在组件顶层调用,事件处理函数中使用 `$fetch` 或 `refresh`
3. 利用 `watch` 和响应式 key 处理依赖变化
4. 根据页面重要性选择 `server` 和 `lazy` 选项
5. 合理管理缓存,避免数据陈旧或重复请求
掌握这些细节,能让 Nuxt3 项目的数据层更加稳健高效。