You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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 }

说明

  1. baseRequest函数:统一处理请求逻辑,接收URL、请求方法、请求数据和额外配置,自动传入自定义的$fetch实例。
  2. useAPI对象:通过Object.assign将原函数与各快捷方法合并,既兼容旧的调用方式,又支持Axios风格的链式调用。
  3. 类型安全:使用泛型和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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.19 17:05:14