在 Nuxt 中自定义 useFetch
如何在 Nuxt 中创建自定义提取器以调用外部 API。
在使用 Nuxt 时,您可能正在进行前端开发并提取外部 API,您可能希望设置一些默认选项以从您的 API 中提取数据。
$fetch
实用函数(由 useFetch
组合式 API 使用)故意不进行全局配置。这一点非常重要,以确保您应用程序中的提取行为保持一致,并且其他集成(如模块)可以依赖于核心实用工具(如 $fetch
)的行为。
然而,Nuxt 提供了一种方法来为您的 API 创建自定义提取器(如果您有多个 API 需要调用,您可以创建多个提取器)。
$fetch
自定义
让我们使用 Nuxt 插件 创建一个自定义的 $fetch
实例。
$fetch
是 ofetch 的一个配置实例,支持在 SSR 期间添加 Nuxt 服务器的基础 URL 以及直接函数调用(避免 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) {
// 请注意,这依赖于 ofetch >= 1.4.0 - 可能需要刷新您的锁文件
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.vue
<script setup>
const { $api } = useNuxtApp()
const { data: modules } = await useAsyncData('modules', () => $api('/modules'))
</script>
使用
useAsyncData
包裹可以 避免在服务器端渲染时进行双重数据提取(服务器与客户端的水合)。useFetch
/useAsyncData
自定义
现在 $api
具有我们想要的逻辑,让我们创建一个 useAPI
组合式 API 来替代 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
})
}
让我们使用新的组合式 API,并拥有一个简洁的组件:
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
是相同的。 Read and edit a live example in Docs > Examples > Advanced > Use Custom Fetch Composable.
我们目前正在讨论寻找一种更简洁的方法让您创建自定义提取器,参见 https://github.com/nuxt/nuxt/issues/14736 。