Nuxt 中的自訂 useFetch
如何在 Nuxt 3 中建立自訂的 fetcher 來呼叫您的外部 API。
當使用 Nuxt 時,您可能會建立前端並從外部 API 獲取資料,並且您可能想要為從您的 API 獲取資料設定一些預設選項。
$fetch
公用程式函式(由 useFetch
composable 使用)有意不進行全域設定。這很重要,這樣在您的應用程式中獲取資料的行為會保持一致,並且其他整合(例如模組)可以依賴於核心公用程式(如 $fetch
)的行為。
不過,Nuxt 提供了一種為您的 API 建立自訂 fetcher 的方法(如果您有多個 API 要呼叫,也可以建立多個 fetcher)。
自訂 $fetch
讓我們使用 Nuxt 外掛建立一個自訂的 $fetch
實例。
$fetch
是 ofetch 的設定實例,它支援新增 Nuxt 伺服器的基本 URL,以及在 SSR 期間進行直接函式呼叫(避免 HTTP 來回傳輸)。讓我們在這裡假設:
- 主要的 API 是 https://api.nuxt.com
- 我們使用 nuxt-auth-utils 將 JWT token 儲存在工作階段中
- 如果 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 外掛,$api
會從 useNuxtApp()
公開,以便直接從 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
的結構相同。我們目前正在討論尋找一種更簡潔的方法讓您建立自訂的 fetcher,請參閱 https://github.com/nuxt/nuxt/issues/14736。