首页
/ airi 仓库前端实战:在 Vue 3 项目中用 VueUse useAxios 以响应式方式驱动 axios 请求

airi 仓库前端实战:在 Vue 3 项目中用 VueUse useAxios 以响应式方式驱动 axios 请求

2026-09-09 18:23:58作者:范靓好Udolf

导读

useAxios 是 VueUse 生态中位于 @vueuse/integrations 的集成型组合式函数(composable),本质上是给 axios 穿上一层 Vue 响应式外壳:它把请求结果、错误、加载态全部收拢进 ref,并额外提供 executeabortcancel 等生命周期控制能力。本文基于 airi 仓库内置的 VueUse 技能文档(.agents/skills/vueuse-functions/references/useAxios.md)展开,先讲清安装、五种调用形态与全部 Options 参数,再结合仓库中 VueUse 技能规则(SKILL.md)与依赖配置,说明这套模式在 Vue 3 / Nuxt 3 项目里的实际落地要点。读完本文,你将能够在任何 Vue 3 项目中用最少的样板代码写出可中断、可重试、可 await 的响应式 HTTP 请求。

一、定位:集成层组合式函数,需要显式引入

在 airi 仓库内置的 VueUse 技能分类中,useAxios 被归类在 @Integrations(第三方库集成)分类下,与 useAsyncValidatoruseCookiesuseFocusTrapuseSortable 等并列,其定位就是 axios 的响应式包装器(Wrapper)

useLocalStorageuseDark 这类开箱即用的核心函数不同,技能文档明确将 useAxios 的调用规则(Invocation)标记为 EXTERNAL,其含义是(见 SKILL.md):

仅当用户已经安装了所需的外部依赖时才使用;否则需要重新考虑,只有真正必要时才要求安装。

也就是说,useAxios 强依赖 axios 运行时库,项目中必须先有 axios 才能使用它。这一规则对 airi 仓库同样适用:仓库的依赖目录清单 pnpm-workspace.yaml 中声明了 @vueuse/core(^14.4.0)与 @vueuse/shared(^14.4.0),但 @vueuse/integrationsaxios 并不在公共依赖目录中;更值得注意的是,pnpm-lock.yaml 显示仓库通过 pnpm 的协议重映射把 axios 解析为 feaxios@^0.0.23 这一 fork 实现。因此在 airi 仓库中引入 useAxios 之前,需要先确认目标子包是否已声明依赖、以及 fork 后的 axios 实现是否满足需求——这正是 EXTERNAL 规则存在的意义。

二、安装:一行命令,锁定 axios 1.x

useAxios 本体随 @vueuse/integrations 一起发布,而它依赖的 axios 需要单独安装:

npm i axios@^1

按 VueUse 技能文档的说明,axios 需要 1.x 大版本(axios@^1)。若使用 pnpm workspace(airi 仓库即采用 pnpm workspace 管理),可以在对应子包的 package.json 中声明:

{
  "dependencies": {
    "axios": "^1",
    "@vueuse/integrations": "^14.4.0"
  }
}

安装完成后即可从集成入口导入:

import { useAxios } from '@vueuse/integrations/useAxios'

三、基础用法:一行代码拿到响应式请求状态

最简调用只需传入 URL,请求会自动立即发起(immediate 默认为 true):

import { useAxios } from '@vueuse/integrations/useAxios'

const { data, isFinished } = useAxios('/api/posts')

与手写 axios.get().then() 不同,这里的 dataisFinished 都是 Vue Ref,模板中可以自动解包、watch 中可以随时订阅,无需手动管理状态同步。

3.1 返回值总览

技能文档给出了完整的返回值清单,整理如下:

属性 类型 说明
data Ref<T> 响应数据(响应体)
response Ref<AxiosResponse> 完整的 axios 响应对象
error Ref<unknown> 请求失败时的错误信息
isFinished Ref<boolean> 请求是否已完成(成功或失败均视为完成)
isLoading Ref<boolean> 请求是否进行中
isAborted Ref<boolean> 请求是否被中止
abort / cancel () => void 中止当前请求(两者互为别名)
execute (url?, config?) => Promise 执行 / 重新执行请求

其中 data 的类型细节取决于是否传入了 initialData:根据类型声明(详见第六节),若传入 initialDatadataRef<T>,否则为 Ref<T | undefined>responseerror 在内部实现为 ShallowRefShallowRef<R | undefined>ShallowRef<unknown | undefined>),并额外暴露了 isCanceled 作为 isAborted 的别名(见 useAxios.md)。

四、传入 Axios 实例:复用拦截器与基础配置

真实项目中通常会用 axios.create() 预先配置 baseURL、超时、请求/响应拦截器等。useAxios 支持把自定义实例作为第二参数传入:

import { useAxios } from '@vueuse/integrations/useAxios'
import axios from 'axios'

const instance = axios.create({
  baseURL: '/api',
})

const { data, isFinished } = useAxios('/posts', instance)

此时 URL 会与实例的 baseURL 合并(最终请求 /api/posts),实例上注册的拦截器、默认 headers、认证逻辑也会一并生效。这是团队项目中推荐的做法——把鉴权、日志、错误统一处理都收敛在实例层。

五、请求配置覆盖:第三种传参形态

如果既要使用实例、又要在本次请求上覆盖配置(例如改走 POST),可以同时传入配置与实例:

import { useAxios } from '@vueuse/integrations/useAxios'
import axios from 'axios'

const instance = axios.create({
  baseURL: '/api',
})

const { data, isFinished } = useAxios('/posts', { method: 'POST' }, instance)

这里的 { method: 'POST' } 是标准的 AxiosRequestConfig,任何 axios 支持的配置项(paramsheaderstimeoutauthdata 等)都可以在此覆盖。技能文档中展示的 useAxios 重载签名(见 useAxios.md)也印证了参数形态的灵活性:

  • useAxios(url)useAxios(url, config?)useAxios(url, instance?)useAxios(url, config, instance)
  • 不传 URL 时:useAxios(config?)useAxios(instance?)useAxios(config, instance),此时返回 EasyUseAxiosReturn

六、手动执行:immediate: falseexecute 的三种用法

默认行为是「传入 URL 立即请求」。当你不希望请求自动发起时,不传 URL 即可,此时 execute 成为唯一触发入口:

import { useAxios } from '@vueuse/integrations/useAxios'

const { execute } = useAxios()
execute(url)

execute 的灵活性体现在它可以接受不同形态的参数:

1. URL 替换:先给 useAxios 传 URL,execute 再传入新 URL 时,新 URL 会替换旧 URL:

import { useAxios } from '@vueuse/integrations/useAxios'

const { execute } = useAxios(url1, {}, { immediate: false })
execute(url2) // 请求 url2,而不是 url1

2. 仅传配置execute 也接受纯配置对象,适合对同一地址发起多次参数不同的请求:

import { useAxios } from '@vueuse/integrations/useAxios'

const { execute } = useAxios(url1, { method: 'GET' }, { immediate: false })
execute({ params: { key: 1 } })
execute({ params: { key: 2 } })

这一形态非常适合「搜索 / 筛选 / 翻页」类场景:地址不变、参数变化,只需反复调用 execute({ params }),无需重建组合式函数。从类型签名看,execute 的参数被定义为 url?: string | AxiosRequestConfig<D>(见 useAxios.md),即 URL 与配置二选一或可组合,返回值为 Promise 化的组合式函数返回值。

七、await 结果:返回对象是 thenable

useAxios 的返回值同时是一个 thenable 对象,因此可以像 Promise 一样被 await——这是「组合式 + 命令式」混合编程的关键能力:

import { useAxios } from '@vueuse/integrations/useAxios'

const { data, isFinished, error } = await useAxios('/api/posts')
// data 此时已被填充

也可以只 await execute 的返回值,等待某次手动触发的请求结束:

import { useAxios } from '@vueuse/integrations/useAxios'

const { execute } = useAxios()
const result = await execute(url)

两种方式各有适用场景:前者适合页面初始化时同步等待首屏数据;后者适合「按钮点击 → 等待结果 → 处理副作用」的事件驱动流程。类型声明中 StrictUseAxiosReturn<T, R, D, O> & Promise<StrictUseAxiosReturn<T, R, D, O>>(见 useAxios.md)正是对这一特性的精确描述——返回值既可直接解构响应式状态,也可整体 await。

八、Options 全参数解析:从默认值到回调钩子

useAxios 的第四个参数是组合式函数自身的选项(注意与第三个参数 axios 配置区分开)。技能文档给出了完整示例:

const { data } = useAxios('/api/posts', config, instance, {
  // 是否立即执行请求(提供 url 时默认 true)
  immediate: true,
  // 是否用 shallowRef 存放 data(默认 true)
  shallow: true,
  // 新请求发起时是否中止上一个未完成的请求(默认 true)
  abortPrevious: true,
  // 执行前是否将 data 重置为初始值(默认 false)
  resetOnExecute: false,
  // 初始数据值
  initialData: [],
  // 回调钩子
  onSuccess: data => console.log('Success:', data),
  onError: error => console.error('Error:', error),
  onFinish: () => console.log('Finished'),
})

对照类型声明(useAxios.md),逐项说明:

选项 类型 默认值 说明
immediate boolean 提供 url 时 true 组合式函数创建时是否自动发起请求
shallow boolean true 使用 shallowRef 存放数据,避免深层响应化带来的开销;数据体很大时保持默认即可
abortPrevious boolean true 每次新 execute 时自动中止上一个未完成的请求,天然防止竞态
resetOnExecute boolean false 每次执行前把 data 重置为初始状态,适合「刷新列表时先清空旧数据」的交互
initialData T 初始数据;传入后 data 类型收紧为 Ref<T>(而非 `Ref<T
onSuccess (data: T) => void 请求成功回调,直接收到解包后的响应数据
onError (e: unknown) => void 请求失败回调
onFinish () => void 请求结束(无论成败)回调,适合统一关闭 loading

选项类型上,UseAxiosOptions<T> 被定义为联合类型(见 useAxios.md):

export type UseAxiosOptions<T = any> =
  | UseAxiosOptionsBase<T>
  | UseAxiosOptionsWithInitialData<T>

即「带初始数据」与「不带初始数据」两条路径,TypeScript 会根据是否传入 initialData 自动收紧 data 的类型。

九、返回类型体系:StrictEasy 两套形态

技能文档末尾给出了完整的类型声明,其中最有价值的是返回值被划分为两套接口:

  • StrictUseAxiosReturn<T, R, D, O>(严格形态):execute 的签名是 (url?: string | AxiosRequestConfig<D>, config?: AxiosRequestConfig<D>) => Promise<StrictUseAxiosReturn<T, R, D, O>>useAxios.md),URL 可选——适用于已传入 URL 的调用;
  • EasyUseAxiosReturn<T, R, D>(简易形态):execute 的签名是 (url: string, config?: AxiosRequestConfig<D>) => Promise<EasyUseAxiosReturn<T, R, D>>useAxios.md),URL 必填——适用于未传 URL(useAxios(config?)useAxios(instance?)useAxios(config, instance))的调用。

两套接口共享的公共字段(useAxios.md)包括:

export interface UseAxiosReturn<
  T,
  R = AxiosResponse<T>,
  _D = any,
  O extends UseAxiosOptions = UseAxiosOptions<T>,
> {
  /** 完整的 axios 响应对象 */
  response: ShallowRef<R | undefined>
  /** 响应数据;传入 initialData 时为 Ref<T>,否则为 Ref<T | undefined> */
  data: O extends UseAxiosOptionsWithInitialData<T>
    ? Ref<T>
    : Ref<T | undefined>
  /** 请求是否已完成 */
  isFinished: Ref<boolean>
  /** 请求是否进行中 */
  isLoading: Ref<boolean>
  /** 请求是否被取消 */
  isAborted: Ref<boolean>
  /** 可能发生的任何错误 */
  error: ShallowRef<unknown | undefined>
  /** 中止当前请求 */
  abort: (message?: string | undefined) => void
  /** abort 的别名 */
  cancel: (message?: string | undefined) => void
  /** isAborted 的别名 */
  isCanceled: Ref<boolean>
}

这里有几个值得注意的细节:

  1. abort(message?) 可以携带中止原因字符串,会被透传给 axios 的 AbortController 取消机制;
  2. data 的类型是条件类型,由选项是否带 initialData 决定,这是「类型随配置自动收紧」的范本;
  3. responseerror 刻意使用 ShallowRef,避免对大型响应体做深度响应化,与 shallow: true 默认值的设计取向一致。

十、在 airi 仓库中的实际落地建议

综合上文,在 airi 这类 pnpm workspace + Vue 3 多端仓库中使用 useAxios,落地路径大致如下:

  1. 确认依赖:在目标子包(如 apps/stage-webpackages/stage-shared)的 package.json 中声明 @vueuse/integrationsaxios。当前仓库公共依赖目录 pnpm-workspace.yaml 已含 @vueuse/core(^14.4.0),版本基调与 VueUse 14 系列一致。
  2. 注意 axios 解析:仓库的 pnpm-lock.yamlaxios 重映射为 feaxios@^0.0.23,因此在仓库内使用 useAxios 前,应确认该 fork 实现与 @vueuse/integrations 的实例化、取消请求等接口兼容,必要时可在子包级覆盖回官方 axios。
  3. 遵循技能调用规则:按 SKILL.mdEXTERNAL 规则,仅当项目已具备 axios 时才使用 useAxios;若只需内置 fetch,应优先考虑同属 Network 分类、无需外部依赖的 useFetch(见 SKILL.md)。
  4. 按场景选择调用形态:接口层统一建 axios.create() 实例承载拦截器;列表刷新用「仅传配置的 execute」;初始化加载用 await useAxios(...);重复触发场景开启 abortPrevious 防止响应乱序。

结语

useAxios 的价值在于把「请求生命周期」完整翻译成了 Vue 的响应式语言:data / error / isLoading / isFinished 四个 ref 覆盖了 UI 的全部状态需求,executeabort 覆盖了交互侧的触发与取消,thenable 返回值则打通了命令式 await 与声明式响应式的边界。配合 .agents/skills/vueuse-functions/references/useAxios.md 中保留的完整类型声明,开发者可以在获得完整类型安全的同时,把 axios 接入成本压缩到最低。

登录后查看全文
热门项目推荐
相关项目推荐

项目优选

收起
kernelkernel
deepin linux kernel
C
33
18
ops-transformerops-transformer
本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。
C++
1.14 K
2.76 K
pytorchpytorch
作为 Ascend for PyTorch 社区的核心组件,TorchNPU 是昇腾专为 PyTorch 打造的深度学习适配插件,使 PyTorch 框架能够直接调用昇腾 NPU,为开发者提供昇腾 AI 处理器的超强算力。
Python
860
1.35 K
docsdocs
暂无描述
Markdown
899
5.83 K
ops-nnops-nn
本项目是CANN提供的神经网络类计算算子库,实现网络在NPU上加速计算。
C++
925
1.85 K
jiuwenswarmjiuwenswarm
JiuwenSwarm 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。
Python
3.84 K
1.02 K
kernelkernel
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
533
601
cann-learning-hubcann-learning-hub
CANN 学习中心仓,支持在线互动运行、边学边练,提供教程、示例与优化方案,一站式助力昇腾开发者快速上手。
Jupyter Notebook
1.03 K
525
ops-mathops-math
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
1.37 K
1.46 K
AscendNPU-IRAscendNPU-IR
AscendNPU-IR是基于MLIR(Multi-Level Intermediate Representation)构建的,面向昇腾亲和算子编译时使用的中间表示,提供昇腾完备表达能力,通过编译优化提升昇腾AI处理器计算效率,支持通过生态框架使能昇腾AI处理器与深度调优
C++
548
395