在使用 Nuxt 时,你可能正在构建前端并获取外部 API 的数据,并且可能希望为从你的 API 获取数据设置一些默认选项。
$fetch 实用函数(由 useFetch composable 使用)有意不设置为全局可配置。这很重要,这样你应用程序中的获取行为就能保持一致,并且其他集成(如模块)可以依赖像 $fetch 这样的核心实用函数的行为。
但是,Nuxt 提供了一种方法来为你(或多个 API 的多个)API 创建一个自定义获取器。
$fetch让我们通过一个 Nuxt 插件创建一个自定义 $fetch 实例。
$fetch 是一个已配置的实例,它支持添加你的 Nuxt 服务器的基础 URL 以及在 SSR 期间的直接函数调用(避免 HTTP 往返)。ofetch$fetch 是一个已配置的实例,它支持添加你的 Nuxt 服务器的基础 URL 以及在 SSR 期间的直接函数调用(避免 HTTP 往返)。在这里,我们假设
401 状态码,我们将用户重定向到 /login 页面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 调用
<script setup>
const { $api } = useNuxtApp()
const { data: modules } = await useAsyncData('modules', () => $api('/modules'))
</script>
useAsyncData 包装可以**避免在服务器端渲染时进行重复数据获取**(服务器和客户端在水合时)。useFetch/useAsyncData现在 $api 已经有了我们想要的逻辑,让我们创建一个 useAPI composable 来替代 useAsyncData + $api 的用法
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,拥有一个漂亮而干净的组件
<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,结构是相同的。