跳到主要内容

Nuxt 中的自定义 useFetch

如何在 Nuxt 中创建用于调用你外部 API 的自定义 fetcher。

在使用 Nuxt 时,你可能在开发前端并获取一个外部 API,并且可能想为从你的 API 获取数据设置一些默认选项。

$fetch 工具函数(被 useFetch 组合式函数使用)特意设计为不可全局配置。这一点很重要,这样你应用中的获取行为才能保持一致,其它集成(如模块)才能依赖像 $fetch 这样的核心工具的行为。

不过,Nuxt 提供了一种方式来为你的 API 创建自定义的 fetcher(如果你有多个 API 要调用,也可以创建多个 fetcher)。

配方:带鉴权的 API 客户端

假设你有一个外部 API 在 https://api.nuxt.com,需要通过 nuxt-auth-utils 进行 JWT 鉴权,并且你想在收到 401 响应时重定向到 /login

app/composables/useAPI.ts
export const useAPI = createUseFetch({
  baseURL: 'https://api.nuxt.com',
  onRequest ({ options }) {
    const { session } = useUserSession()
    if (session.value?.token) {
      options.headers.set('Authorization', `Bearer ${session.value.token}`)
    }
  },
  async onResponseError ({ response }) {
    if (response.status === 401) {
      await navigateTo('/login')
    }
  },
})

现在对 useAPI 的每次调用都会自动带上鉴权头,并处理 401 重定向:

app/pages/dashboard.vue
<script setup lang="ts">
const { data: profile } = await useAPI('/me')
const { data: orders } = await useAPI('/orders')
</script>

配方:自定义 $fetch 实例

如果你需要更低层的控制,你可以用 Nuxt 插件 创建一个自定义的 $fetch 实例,并直接配合 useAsyncData 使用,或将其传递给 createUseFetch

$fetchofetch 的一个配置过的实例,它支持添加你的 Nuxt 服务器的 base URL,以及在 SSR 期间直接进行函数调用(避免 HTTP 往返)。
app/plugins/api.ts
export default defineNuxtPlugin((nuxtApp) => {
  const { session } = useUserSession()

  const api = $fetch.create({
    baseURL: 'https://api.nuxt.com',
    onRequest ({ request, options, error }) {
      if (session.value?.token) {
        options.headers.set('Authorization', `Bearer ${session.value?.token}`)
      }
    },
    async onResponseError ({ response }) {
      if (response.status === 401) {
        await nuxtApp.runWithContext(() => navigateTo('/login'))
      }
    },
  })

  return {
    provide: {
      api,
    },
  }
})

然后你可以直接使用这个自定义的 $fetch 实例:

app/app.vue
<script setup>
const { $api } = useNuxtApp()
const { data: modules } = await useAsyncData('modules', () => $api('/modules'))
</script>
useAsyncData 包裹可以避免在服务端渲染时(服务端与水合时的客户端)重复获取两次数据