Vue 3 中调用 API 的核心是使用组合式函数封装请求逻辑,聚焦发起请求、处理响应、暴露 execute 接口,返回 { data, error, loading, execute },支持手动触发、错误加载状态响应式绑定及进阶能力如参数化、取消、缓存与防抖。
在 Vue 3 的 setup 中调用 API,核心不是“怎么发请求”,而是“如何组织得清晰、可复用、易测试、不污染组件逻辑”。直接在 setup 里写 axios.get() 看似快,但很快会陷入重复处理 loading、error、缓存、取消请求的泥潭。真正的优雅,来自组合式函数(Composable)的合理封装。
一个高质量的 API 组合式函数,应聚焦三件事:发起请求、处理响应结构、暴露可控的执行接口。它不该直接修改组件内的 ref,也不该主动触发 UI 更新。
{ data, error, loading, execute },语义清晰,按需使用execute 是函数,而非自动执行——让调用方决定何时拉数据(比如点击后、路由就绪后)ref 包裹,方便在模板中响应式绑定(v-if="loading")以下是一个生产可用的最小可行封装(以 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 }}
在组件中使用时干净利落:
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> ) }})
真实业务中,你很快会需要这些能力。它们不该堆在组件里,而应沉淀到组合式函数中:
url 改为函数,如 (id: string) => `/api/user/${id}`,execute 接收参数并重置状态AxiosController 或 AbortController,在 execute 中生成新 controller,并在下一次调用前 abort 上次(尤其适合搜索输入框)url + JSON.stringify(params) 对应的结果,命中则直接 resolve,避免重复请求execute(如搜索),用 lodash.debounce 包一层,返回新的防抖函数封装是为了简化,不是隐藏复杂度。几个常见反模式要警惕:
useRequest 的万能函数里——参数越来越多,类型难推导,维护成本飙升notification.success() 或 router.push() —— 违反关注点分离,组件失去控制权res.headers、res.status),导致分页、鉴权头等场景无法处理any 或 unknown 敷衍,失去类型安全优势好的组合式函数,应该像乐高积木:单个功能纯粹,拼起来却能构建复杂应用。它不替你做决定,只给你稳当的把手。