如何在Nuxt 3中为自定义Fetch插件实现方法式调用封装
Nuxt3 封装useAPI实现Axios风格调用
问题背景
正在将Nuxt2应用迁移至Nuxt3(同步升级Vue2到Vue3),原项目使用Axios处理HTTP请求,但Nuxt3不再支持Axios,Vue3内置了Fetch API。已基于自定义Fetch实现了可用的useAPI composable,但希望封装成Axios那样的链式调用风格。
当前调用方式:
const resp = await useAPI(`/user/${url}`, {method: "POST", body: data})
期望调用方式:
const resp = await useAPI.post(`/user/${url}`, data, {/* 额外请求头 */})
现有代码
自定义Fetch插件
export default defineNuxtPlugin((nuxtApp) => { const token = useCookie('token') const api = $fetch.create({ baseURL: "http://localhost:3012", onRequest({ request, options, error }) { if (token.value) { const headers = options.headers ||= {} if (Array.isArray(headers)) { headers.push(['Authorization', `Bearer ${token.value}`]) } else if (headers instanceof Headers) { headers.set('Authorization', `Bearer ${token.value}`) } else { headers.Authorization = `Bearer ${token.value}` } } }, async onResponseError({ response }) { if (response.status === 401) { await nuxtApp.runWithContext(() => navigateTo('/login')) } } }) // 暴露给useNuxtApp().$api return { provide: { api } } })
现有useAPI Composable
import type { UseFetchOptions } from 'nuxt/app' export function useAPI<T>( url: string | (() => string), options: UseFetchOptions<T> = {}, ) { return useFetch(url, { ...options, $fetch: useNuxtApp().$api as any }) }
解决方案:改造useAPI实现Axios风格调用
将useAPI从单一函数改造为包含各请求方法快捷调用的对象,同时保留原调用方式的兼容性,代码如下:
import type { UseFetchOptions } from 'nuxt/app' // 定义支持的HTTP请求方法类型 type HttpMethod = 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH' // 封装通用请求逻辑 async function baseRequest<T>( url: string | (() => string), method: HttpMethod, data?: any, options: Omit<UseFetchOptions<T>, 'method' | 'body'> = {} ) { return useFetch<T>(url, { method, ...(data && { body: data }), ...options, $fetch: useNuxtApp().$api as any }) } // 创建useAPI对象,合并原函数与快捷方法 const useAPI = Object.assign( // 保留原调用方式,兼容旧代码 <T>(url: string | (() => string), options: UseFetchOptions<T> = {}) => { return useFetch<T>(url, { ...options, $fetch: useNuxtApp().$api as any }) }, // 添加各请求方法的快捷调用 { get: <T>(url: string | (() => string), options?: Omit<UseFetchOptions<T>, 'method'>) => baseRequest<T>(url, 'GET', undefined, options), post: <T>(url: string | (() => string), data?: any, options?: Omit<UseFetchOptions<T>, 'method' | 'body'>) => baseRequest<T>(url, 'POST', data, options), put: <T>(url: string | (() => string), data?: any, options?: Omit<UseFetchOptions<T>, 'method' | 'body'>) => baseRequest<T>(url, 'PUT', data, options), delete: <T>(url: string | (() => string), options?: Omit<UseFetchOptions<T>, 'method'>) => baseRequest<T>(url, 'DELETE', undefined, options), patch: <T>(url: string | (() => string), data?: any, options?: Omit<UseFetchOptions<T>, 'method' | 'body'>) => baseRequest<T>(url, 'PATCH', data, options) } ) export { useAPI }
说明
- baseRequest函数:统一处理请求逻辑,接收URL、请求方法、请求数据和额外配置,自动传入自定义的
$fetch实例。 - useAPI对象:通过
Object.assign将原函数与各快捷方法合并,既兼容旧的调用方式,又支持Axios风格的链式调用。 - 类型安全:使用泛型和
Omit类型排除已由快捷方法处理的配置项,保证类型校验正常工作。
使用示例
// POST请求,带数据和自定义头 const resp = await useAPI.post(`/user/${url}`, data, { headers: { 'X-Custom-Header': 'value' } }) // GET请求 const userResp = await useAPI.get('/user/123') // 保留原调用方式(兼容旧代码) const oldStyleResp = await useAPI(`/user/${url}`, { method: "POST", body: data })
内容的提问来源于stack exchange,提问作者Manuel Duarte
相关产品推荐
相关产品推荐

