在 Nuxt 中自定义 useFetch
如何创建自定义获取器以在 Nuxt 中调用外部 API。
在使用 Nuxt 时,您可能正在制作前端并获取外部 API,您可能想要为从 API 获取设置一些默认选项。
$fetch``实用函数(由 useFetch``组合式函数使用)故意不进行全局配置。这很重要,以便应用程序中的获取行为保持一致,其他集成(如模块)可以依赖核心实用程序(如 $fetch)的行为。
但是,Nuxt 提供了一种为您的 API 创建自定义获取器的方法(如果您有多个 API 要调用,也可以创建多个获取器)。
自定义 $fetch
让我们使用 Nuxt 插件创建一个自定义的 $fetch 实例。
$fetch 是 ofetch的配置实例,它支持添加 Nuxt 服务器的 base URL 以及在 SSR 期间进行直接函数调用(避免 HTTP 往返)。让我们在这里假设:
- 主要 API 是 https://api.nuxt.com
- 我们使用 nuxt-auth-utils在会话中存储 JWT 令牌
- 如果 API 响应
401状态码,我们将用户重定向到/login页面
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) {
// 请注意,这依赖于 ofetch >= 1.4.0 - 您可能需要刷新您的 lockfile
options.headers.set('Authorization', `Bearer ${session.value?.token}`)
}
},
async onResponseError ({ response }) {
if (response.status === 401) {
await nuxtApp.runWithContext(() => navigateTo('/login'))
}
},
})
// 暴露给 useNuxtApp().$api
return {
provide: {
api,
},
}
})
使用此 Nuxt 插件,$api 从 useNuxtApp() 暴露,以便直接从 Vue 组件进行 API 调用:
app/app.vue
<script setup>
const { $api } = useNuxtApp()
const { data: modules } = await useAsyncData('modules', () => $api('/modules'))
</script>
使用 `useAsyncData``包装在进行服务器端渲染时避免双重数据获取(服务器和客户端在水合时)。
自定义 useFetch/useAsyncData
既然 $api 具有我们想要的逻辑,让我们创建一个 useAPI 组合式函数来替换 useAsyncData + $api 的使用:
app/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,
})
}
让我们使用新的组合式函数,拥有一个漂亮而干净的组件:
app/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
status: number
}
export function useAPI<T> (
url: string | (() => string),
options?: UseFetchOptions<T>,
) {
return useFetch<T, FetchError<CustomError>>(url, {
...options,
$fetch: useNuxtApp().$api,
})
}
此示例演示了如何使用自定义
useFetch,但对于自定义 useAsyncData,相同的结构也是相同的。我们目前正在讨论找到一种更清洁的方法让您创建自定义获取器,请参阅 https://github.com/nuxt/nuxt/issues/14736。