一、为什么选择VueUse的useFetch?

在Vue3生态中,HTTP请求处理一直是开发者关注的重点。传统方案如axios需要手动管理请求状态,而VueUse提供的useFetch通过组合式API实现了开箱即用的响应式请求管理。对比发现:

  • 代码量减少:自动处理loadingerror状态
  • 响应式集成:数据变更自动触发视图更新
  • TS友好:完整的TypeScript类型推断
  • 超时重试:内置请求重试机制
  • 体积轻盈:仅需引入@vueuse/core(约4KB)

二、快速搭建基础项目环境(技术栈明确声明)

本文使用以下技术栈组合:

  • Vue3:组合式API基础框架
  • Vite4:构建工具
  • @vueuse/core 9.0:工具库
  • TypeScript5:语言支持
# 使用以下命令创建初始项目
npm create vite@latest vueuse-fetch-demo -- --template vue-ts
cd vueuse-fetch-demo
npm install @vueuse/core

三、useFetch基础用法示例

1. GET请求基础实现

<script setup lang="ts">
import { useFetch } from '@vueuse/core'

// 基础GET请求(含智能类型推断)
const { data, isFetching, error } = useFetch('https://api.example.com/posts/1')
</script>

<template>
  <!-- 响应式展示层 -->
  <div v-if="isFetching">加载动画...</div>
  <div v-else-if="error">错误:{{ error.message }}</div>
  <div v-else>{{ data }}</div>
</template>

2. POST请求配合拦截器

// utils/request.ts
export const useCustomFetch = (url: string, options?: any) => {
  return useFetch(url, {
    // 统一请求配置
    timeout: 10000,
    retry: 3,
    
    // 请求拦截
    beforeFetch({ options }) {
      options.headers = {
        ...options.headers,
        Authorization: `Bearer ${localStorage.getItem('token')}`
      }
      return { options }
    },
    
    // 响应拦截
    afterFetch(ctx) {
      if (ctx.data.code !== 200) {
        throw new Error(ctx.data.message)
      }
      ctx.data = ctx.data.result
      return ctx
    }
  }).json() // 自动解析JSON
}

// 组件内使用
const { execute } = useCustomFetch('https://api.example.com/login', {
  method: 'POST',
  body: JSON.stringify({ username: 'admin', password: '123456' })
})

四、高级功能实战演示

1. 请求取消与竞态处理

const { abort, execute } = useFetch('https://api.example.com/search')

// 用户触发搜索
const handleSearch = async (keyword: string) => {
  // 终止进行中的请求
  if (abort) abort()
  
  // 发起新请求
  await execute({
    query: { q: keyword }
  }).then(({ data }) => {
    console.log('最新结果:', data)
  })
}

2. 自动重试与超时策略

// 配置重试策略
const { data } = useFetch('https://api.example.com/status', {
  retry: 5,                          // 最大重试次数
  retryDelay: 1000,                  // 重试间隔
  timeout: 3000,                     // 单次请求超时
  onFetchError(ctx) {
    console.log('最终请求失败:', ctx.error)
  }
})

3. 实时数据轮询

import { useIntervalFn } from '@vueuse/core'

const { data, execute } = useFetch('https://api.example.com/stock')

// 每10秒刷新数据
const { pause, resume } = useIntervalFn(() => {
  execute()
}, 10000)

// 页面隐藏时暂停轮询
const { stop } = usePageVisibility({
  onChange: (visible) => {
    visible ? resume() : pause()
  }
})

五、企业级应用场景剖析

1. 高频数据展示看板

// dashboard.vue
const { data: salesData } = useFetch('/api/sales', {
  refetch: true, // 窗口聚焦时自动刷新
  initialData: [] // 防止页面抖动
})

2. 表单提交防抖优化

const { execute } = useFetch('/api/submit', { 
  immediate: false 
})

// 带500ms防抖的提交
const handleSubmit = useDebounceFn(async () => {
  await execute({
    method: 'POST',
    body: formData.value
  })
}, 500)

六、技术方案对比分析

优势亮点:

  1. 响应式状态集成:自动同步loading/error/data到视图
  2. 配置继承性:通过拦截器实现全局配置
  3. 体积效益:无需额外安装HTTP库
  4. 组合式扩展:轻松配合useDebounceFn等工具

已知局限性:

  1. 多请求管理:缺乏类似axios.all的批处理方案
  2. 上传进度:不支持文件上传进度监听
  3. 缓存策略:需自行实现缓存逻辑

七、关键注意事项

1. 服务端渲染(SSR)适配

// 仅在客户端执行请求
const { data } = useFetch('https://api.example.com', {
  server: false // 禁用SSR
})

2. TypeScript类型强化

interface UserProfile {
  id: number
  name: string
  avatar: string
}

// 明确响应类型
const { data } = useFetch<UserProfile>('https://api.example.com/me')
  .json()

3. 性能优化策略

// 大文件下载使用分块处理
const { data } = useFetch('/api/large-file', {
  refetch: false,       // 禁止重复请求
  timeout: 0            // 取消超时限制
})

八、完整技术方案总结

经过深度实践验证,useFetch在以下场景表现卓越:

  • 需要快速实现CRUD操作的内部系统
  • 对包体积敏感的低代码平台
  • 需要高频更新数据的可视化项目
  • 重视开发体验的初创团队

推荐配合策略:

  • 结合useStorage做本地缓存
  • 使用useFetch处理基础请求
  • 复杂场景配合axios扩展