人人都会AI编程

与传统请求封装的优劣势对比

更新时间:2026-07-09

在 Vue 项目中,大多数团队都会对 Axios 进行二次封装,统一处理请求拦截、错误提示、Token 注入等。这套方案我们称为“传统请求封装”。而 TanStack Query(Vue Query)在前端请求管理上引入了一套不同的模式——以服务端状态为中心,把请求结果当作缓存来管理。下面从真实开发场景出发,对比两者的优劣。

传统请求封装:你在手动管理一切

典型的传统封装长这样:

// api/user.js
import request from '@/utils/request'
export const getUserInfo = () => request.get('/api/user/info')

// 组件中使用
import { getUserInfo } from '@/api/user'
const userInfo = ref(null)
const loading = ref(false)
onMounted(async () => {
  loading.value = true
  try {
    userInfo.value = await getUserInfo()
  } catch (e) {
    // 处理错误
  } finally {
    loading.value = false
  }
})

它的优势是简单直接:你发起一个请求,拿到数据,存到组件本地状态,界面就渲染了。所有流程都在你的掌控之中,没有额外的抽象层。

但痛点也很明显:

  • Loading / Error 状态需要手动维护。每个请求都要定义 loadingerror 变量,写 try/catch/finally,代码重复量极大。
  • 数据缓存完全靠自己。如果多个页面都需要用户信息,要么每次都请求一遍(浪费流量),要么把数据存到全局 Store 里手动同步(数据何时过期?谁来清除?)。
  • 请求竞态问题。快速切换筛选条件时,后发的请求可能比先发的请求更早返回,导致界面显示旧数据。你需要手动添加请求标识或取消令牌。
  • 乐观更新、分页、无限滚动等高级特性需要自己实现,代码量陡增。

TanStack Query:把请求当缓存管理

同样的场景,用 Vue Query 会变成:

import { useQuery } from '@tanstack/vue-query'
import { getUserInfo } from '@/api/user'

const { data: userInfo, isLoading, error } = useQuery({
  queryKey: ['userInfo'],
  queryFn: getUserInfo,
  staleTime: 5 * 60 * 1000  // 5分钟内不重新请求
})

优势一目了然

  • 自动管理请求状态isLoadingisErrordata 等状态由库返回,你不再需要定义任何辅助变量。
  • 内置缓存与去重。相同的 queryKeystaleTime 内不会重复请求,而是直接从缓存读取;同时多个组件使用同一个 query 时,也会合并请求,避免重复网络调用。
  • 竞态问题自动解决。Vue Query 会丢弃过期的请求响应,只使用最新的。
  • 开箱即用的高级功能。分页(useQuery 加参数)、无限滚动(useInfiniteQuery)、乐观更新(useMutationonMutate)、后台自动刷新(refetchInterval)等都内置或极简实现。
  • 请求与组件解耦。数据获取逻辑可独立于组件,在父组件或路由守卫中预取,提升用户体验。

劣势与适用边界

TanStack Query 不是银弹,它也有不适用的场景:

  • 简单场景下反而增加复杂度。如果只是几个页面里偶尔用到的接口,用传统封装配合 fetch 或 Axios 更直接,引入 Query 的 queryKey 管理、QueryClientProvider 等概念反而多余。
  • 学习成本。团队需要理解 staleTimecacheTimeinvalidateQueries 等缓存策略,以及 mutation 与 query 的区别,这对新手不友好。
  • 非 RESTful 接口适配成本。如果后端接口设计不符合“请求-响应”范式(比如 WebSocket 推送、GraphQL),Query 的缓存模型需要额外定制,不一定比原生写法省心。
  • 请求封装层依然需要。Query 本身不负责请求发送,queryFn 内部还是要用你自己封装的 Axios 或 fetch 实例,所以传统封装中的 Token 注入、错误统一处理依然存在,只是换了个地方写。

选型建议

| 场景 | 推荐方案 |
|------|----------|
| 管理后台、数据密集型应用 | TanStack Query,减少数据同步样板代码 |
| 请求少、交互简单的页面 | 传统 Axios 封装,保持轻量 |
| 实时性要求高的场景(如看板) | 传统封装 + WebSocket,或结合 Query 的 refetchInterval |
| 逐渐迁移 | 可以两者共存,核心数据用 Query,一次性操作仍用 Axios 直接调用 |

一句话总结:TanStack Query 解决的是“怎么把服务端数据舒服地同步到 UI”的问题,而不是“怎么发请求”的问题。如果你的项目里 loadingerror、缓存失效这些代码占比过高,它就是值得投入的方案;如果你只是偶尔调个接口渲染一下页面,传统封装已经足够。