透過 100 多個技巧的集合來學習 Nuxt!

在 Nuxt 中自訂 useFetch

如何在 Nuxt 3 中建立自訂的 fetcher 以呼叫您的外部 API。

當您使用 Nuxt 時,您可能會開發前端並從外部 API 獲取資料,並且您可能想要為從您的 API 獲取資料設定一些預設選項。

$fetch 實用工具函式(由 useFetch composable 使用)有意地不設定為全域可配置。這很重要,這樣在您的應用程式中的獲取行為才能保持一致,而其他整合(例如模組)可以依賴像 $fetch 這樣的核心實用工具的行為。

但是,Nuxt 提供了一種為您的 API 建立自訂 fetcher 的方法(如果您有多個 API 要呼叫,也可以建立多個 fetcher)。

自訂 $fetch

讓我們使用 Nuxt 插件建立一個自訂的 $fetch 實例。

$fetchofetch 的一個已配置實例,它支援新增您的 Nuxt 伺服器的基礎 URL,以及在 SSR 期間的直接函式呼叫(避免 HTTP 往返)。

讓我們在這裡假設

  • 主要 API 是 https://api.nuxt.com
  • 我們正在使用 nuxt-auth-utils 將 JWT 令牌儲存在工作階段中
  • 如果 API 回應 401 狀態碼,我們會將使用者重新導向到 /login 頁面
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) {
        // note that this relies on ofetch >= 1.4.0 - you may need to refresh your lockfile
        options.headers.set('Authorization', `Bearer ${session.value?.token}`)
      }
    },
    async onResponseError({ response }) {
      if (response.status === 401) {
        await nuxtApp.runWithContext(() => navigateTo('/login'))
      }
    }
  })

  // Expose to useNuxtApp().$api
  return {
    provide: {
      api
    }
  }
})

透過這個 Nuxt 插件,$apiuseNuxtApp() 暴露出來,以便直接從 Vue 組件進行 API 呼叫

app.vue
<script setup>
const { $api } = useNuxtApp()
const { data: modules } = await useAsyncData('modules', () => $api('/modules'))
</script>
使用 useAsyncData 包裝可以**避免在進行伺服器端渲染時重複獲取資料**(伺服器和客戶端在 hydration 時)。

自訂 useFetch/useAsyncData

現在 $api 具有我們想要的邏輯,讓我們建立一個 useAPI composable 來取代 useAsyncData + $api 的用法

composables/useAPI.ts
import type { UseFetchOptions } from 'nuxt/app'

export function useAPI<T>(
  url: string | (() => string),
  options?: UseFetchOptions<T>,
) {
  return useFetch(url, {
    ...options,
    $fetch: useNuxtApp().$api as typeof $fetch
  })
}

讓我們使用新的 composable 並擁有一個美觀且乾淨的組件

app.vue
<script setup>
const { data: modules } = await useAPI('/modules')
</script>

如果您想要自訂任何傳回的錯誤類型,您也可以這樣做

import type { FetchError } from 'ofetch'
import type { UseFetchOptions } from 'nuxt/app'

interface CustomError {
  message: string
  statusCode: number
}

export function useAPI<T>(
  url: string | (() => string),
  options?: UseFetchOptions<T>,
) {
  return useFetch<T, FetchError<CustomError>>(url, {
    ...options,
    $fetch: useNuxtApp().$api
  })
}
這個範例示範了如何使用自訂的 useFetch,但對於自訂的 useAsyncData 來說,結構是相同的。
文件 > 範例 > 進階 > 使用自訂 Fetch Composable 中閱讀和編輯即時範例。
觀看關於 Nuxt 中自訂 $fetch 和 Repository Pattern 的影片。
我們目前正在討論尋找一種更簡潔的方式讓您建立自訂 fetcher,請參閱 https://github.com/nuxt/nuxt/issues/14736