vue 3 中调用 api 的核心是使用组合式函数封装请求逻辑,聚焦发起请求、处理响应、暴露 execute 接口,返回 { data, error, loading, execute },支持手动触发、错误加载状态响应式绑定及进阶能力如参数化、取消、缓存与防抖。

在 Vue 3 的 setup 中调用 API,核心不是“怎么发请求”,而是“如何组织得清晰、可复用、易测试、不污染组件逻辑”。直接在 setup 里写 axios.get() 看似快,但很快会陷入重复处理 loading、error、缓存、取消请求的泥潭。真正的优雅,来自组合式函数(Composable)的合理封装。
明确职责:组合式函数只管“请求逻辑”,不管“UI 状态”
一个高质量的 API 组合式函数,应聚焦三件事:发起请求、处理响应结构、暴露可控的执行接口。它不该直接修改组件内的 ref,也不该主动触发 UI 更新。
- 返回值推荐解构对象:
{ data, error, loading, execute },语义清晰,按需使用 -
execute是函数,而非自动执行——让调用方决定何时拉数据(比如点击后、路由就绪后) - 错误和加载状态用
ref包裹,方便在模板中响应式绑定(v-if="loading")
基础封装:带 loading 和 error 处理的通用模式
以下是一个生产可用的最小可行封装(以 axios 为例):
import { ref, Ref } from 'vue'
import axios from 'axios'
interface UseApiOptions {
manual?: boolean // 是否手动触发,默认 false(自动执行)
}
export function useApi<t>(url: string, options: UseApiOptions = {}) {
const data = ref<t null>(null)
const error = ref<error null>(null)
const loading = ref(false)
const execute = async () => {
loading.value = true
error.value = null
try {
const res = await axios.get<t>(url)
data.value = res.data
return res.data
} catch (e) {
error.value = e as Error
throw e
} finally {
loading.value = false
}
}
if (!options.manual) {
execute()
}
return {
data,
error,
loading,
execute
}
}</t></error></t></t>
在组件中使用时干净利落:
import { useApi } from '@/composables/useApi'
export default defineComponent({
setup() {
const { data, loading, error, execute } = useApi<user>('/api/user/1')
const handleRefresh = () => execute()
return () => (
<div>
{loading.value ? '加载中...' : null}
{error.value ? `错误:${error.value.message}` : null}
{data.value ? <h2>{data.value.name}</h2> : null}
<button onclick="{handleRefresh}">刷新</button>
</div>
)
}
})</user>
进阶技巧:支持参数、取消请求、缓存与防抖
真实业务中,你很快会需要这些能力。它们不该堆在组件里,而应沉淀到组合式函数中:
-
动态参数:把
url改为函数,如(id: string) => `/api/user/${id}`,execute接收参数并重置状态 -
请求取消:用
AxiosController或AbortController,在execute中生成新 controller,并在下一次调用前 abort 上次(尤其适合搜索输入框) -
简单内存缓存:用 Map 缓存
url + JSON.stringify(params)对应的结果,命中则直接 resolve,避免重复请求 -
节流/防抖:对高频触发的
execute(如搜索),用lodash.debounce包一层,返回新的防抖函数
避坑提醒:别让组合式函数变成“黑盒”
封装是为了简化,不是隐藏复杂度。几个常见反模式要警惕:
- 把所有 API 请求都塞进一个叫
useRequest的万能函数里——参数越来越多,类型难推导,维护成本飙升 - 在组合式函数里直接调用
notification.success()或router.push()—— 违反关注点分离,组件失去控制权 - 不暴露原始响应(如
res.headers、res.status),导致分页、鉴权头等场景无法处理 - 忽略 TypeScript 类型推导,用
any或unknown敷衍,失去类型安全优势
好的组合式函数,应该像乐高积木:单个功能纯粹,拼起来却能构建复杂应用。它不替你做决定,只给你稳当的把手。
大量免费API接口:立即使用
涵盖生活服务API、金融科技API、企业工商API、等相关的API接口服务。免费API接口可安全、合规地连接上下游,为数据API应用能力赋能!










