十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Nuxt `createUseFetch`:工厂函数定制携带预置默认值的 `useFetch` 组合式函数

Nuxt `createUseFetch`:工厂函数定制携带预置默认值的 `useFetch` 组合式函数 NuxtcreateUseFetch工厂函数定制携带预置默认值的useFetch组合式函数【免费下载链接】nuxtthe full-stack Vue framework项目地址: https://gitcode.com/GitHub_Trending/nu/nuxt在 Nuxt 应用中$fetch与useFetch出于全局一致性考虑刻意不支持全局配置而createUseFetch则提供了官方推荐的替代路径它是一个工厂函数compiler macro让你以“默认配置 调用点覆盖”的方式快速派生出一个完全类型化的自定义数据请求组合式函数例如统一封装baseURL、鉴权头、401 跳转等。读完本文你将掌握createUseFetch的使用规则、编译器宏原理、默认值与覆盖值两种合并模式的差异以及如何把它与自定义$fetch实例结合。关联 API 文档create-use-fetch.md源码实现在 packages/nuxt/src/app/composables/fetch.ts。为什么需要createUseFetch在 custom-usefetch.md 中解释了背景Nuxt 中的useFetch是useAsyncData与$fetch的便捷封装而$fetch刻意设计为不可全局配置。这样能保证应用内的请求行为保持一致也让生态模块可以依赖核心工具函数的行为。因此当团队需要“所有请求都带上某个baseURL”“统一附加 JWT 鉴权头”“遇到 401 统一跳转登录页”等场景时既不应该修改全局$fetch也不应该在每个组件里重复书写这些选项——正确做法是用createUseFetch创建多个“专用于某一 API 的 fetcher”。createUseFetch创建出的组合式函数与useFetch签名、返回值完全一致只是把工厂传入的选项作为内建默认值或强制覆盖值烘焙进去。返回结果依然完全类型化基于服务端路由的类型提示、响应类型推断、key 自动生成与请求去重等能力全部保留。快速上手在composables/目录或任何被 Nuxt 编译器扫描的目录中导出一个由createUseFetch创建的组合式函数export const useAPI createUseFetch({ baseURL: https://api.nuxt.com, })随后在页面里直接使用script setup langts const { data: modules } await useAPI(/modules) /script这里/modules会被拼到默认的baseURL之后得到https://api.nuxt.com/modules。调用者既可以完全省略选项也可以在第二个参数位置覆盖或补充任意选项——因为派生出的useAPI拥有与useFetch相同的签名与返回类型。编译器宏与使用约束::note 这是一段必须强调的关键约束createUseFetch本质是一个compiler macro而不是普通的运行时函数。它必须以exported 声明的形式出现在composables/目录或任何被 Nuxt 编译器扫描的目录中Nuxt 会在构建期自动为派生出的组合式函数注入去重 keyde-duplication key。这一机制在源码中有完整体现真实实现位于 fetch.ts它通过defineKeyedFunctionFactory注册该辅助函数定义在 packages/nuxt/src/compiler/runtime/index.ts。被注册的“占位符”函数若未被编译器替换而直接调用会抛出NUXT_E1007诊断错误对应文档见 errors/e1007.md。编译器插件 packages/nuxt/src/compiler/plugins/keyed-function-factories.ts 专门扫描export const x createUseFetch(...)/export default createUseFetch(...)这类导出声明把派生函数收集进optimization.keyedComposables以便后续在调用点注入自动 key同时该插件的 transform 阶段会把源码中的createUseFetch(...)改写为createUseFetch.__nuxt_factory(...)。createUseFetch已加入自动导入预设packages/nuxt/src/imports/presets.ts因此在composables/等目录内无需手动import即可使用。单元测试 packages/nuxt/test/keyed-function-factories.test.ts 验证了上述扫描行为包括具名导出、默认导出以及保留原始命名的场景。从源码结构看这套“keyed function factory”机制还被createUseAsyncData复用见 packages/nuxt/src/app/composables/asyncData.ts 与对应文档 create-use-async-data.md。另外一个细节值得留意既然createUseFetch是保留的宏名就不要把自定义函数命名为useFetch需要自定义变体时使用createUseFetchuseFetch文档中的 warning 也强调了这一点见 use-fetch.md。类型签名官方文档给出了两种重载function createUseFetch ( options?: PartialUseFetchOptions, ): typeof useFetch function createUseFetch ( options: (callerOptions: UseFetchOptions) PartialUseFetchOptions, ): typeof useFetch第一种传入普通对象第二种传入函数接收调用方传入的选项作为参数。二者对应下面两种完全不同的合并策略。对应到源码的CreateUseFetch接口定义其泛型参数围绕请求类型FReqT、HTTP 方法FMethod、响应类型FResT、数据类型FDataT、pick键集FPickKeys与默认值类型FDefaultT展开以便把派生组合式函数的调用签名精确约束到与useFetch一致见 fetch.ts。可用的选项createUseFetch接受与useFetch完全相同的全部选项见 use-fetch.md 的Parameters一节包括baseURL、headers、query、onRequest、onResponse、server、lazy、transform、getCachedData、enabled、serialize等。常用选项概览选项类型默认值说明keyMaybeRefOrGetterstring自动生成去重 key未提供时由 URL、选项与调用点位置生成methodMaybeRefOrGetterstringGETHTTP 请求方法query/paramsMaybeRefOrGetterSearchParams—追加到 URL 的查询参数对象自动 stringifybaseURLMaybeRefOrGetterstring—请求的基础 URLheadersMaybeRefOrGetterHeadersInit—请求头bodyMaybeRefOrGetterRequestBody—请求体对象自动 stringifycachefalse \| string—缓存控制可传入 Fetch API 取值serverbooleantrue是否在服务端发起请求lazybooleanfalse为true时不阻塞路由导航immediatebooleantrue为false时不立即发起请求transform(input) DataT \| PromiseDataT—请求成功后对结果做变换pickstring[]—只从结果中挑选指定字段watchMultiWatchSources \| false—监听响应式源并自动重新请求false关闭getCachedData(key, nuxtApp, ctx) DataT \| undefined内建实现返回缓存数据deepbooleanfalse是否以深层 ref 返回数据dedupecancel \| defercancel同一 key 并发请求去重策略enabledbooleantrue请求门禁false时阻止一切执行并取消在途请求serializebooleantrue是否把已解析数据写入 Nuxt payload$fetchtypeof globalThis.$fetch—自定义$fetch实现除此之外createUseFetch的选项同样支持 ofetch 拦截器onRequest、onRequestError、onResponse、onResponseError你可以在派生组合式函数中统一处理鉴权与错误。默认模式与覆盖模式文档将合并行为明确区分为两种模式这是createUseFetch使用上最容易混淆、也最关键的地方。默认模式传入普通对象当传入普通对象时工厂选项仅作为默认值调用方可以覆盖其中任何一项export const useAPI createUseFetch({ baseURL: https://api.nuxt.com, lazy: true, })// 使用默认的 baseURL const { data } await useAPI(/modules) // 调用方覆盖 baseURL const { data } await useAPI(/modules, { baseURL: https://other-api.com })源码中对应的合并顺序是{ ...工厂选项, ...调用方选项 }即调用方选项优先级更高见 fetch.tscreateUseAsyncData内部的“默认模式”则采用逐键填充方式——仅当调用方未显式提供该选项时才写入工厂默认值见 asyncData.ts。覆盖模式传入函数当传入函数时语义完全反转工厂返回的选项会覆盖调用方传入的选项。函数会收到调用方的选项作为实参因此你可以读取它们来计算自己的覆盖值// baseURL 永远被强制为这个值无论调用方传入什么 export const useAPI createUseFetch(callerOptions ({ baseURL: https://api.nuxt.com, }))源码中对应的合并顺序是{ ...调用方选项, ...工厂函数返回的选项 }工厂值优先级更高fetch.ts。这种模式非常适合强制那些不允许调用方更改的设置例如固定的认证头或某个不应被篡改的 base URL。与自定义$fetch实例结合你还可以把自定义的$fetch实例传给createUseFetchexport const useAPI createUseFetch(callerOptions ({ $fetch: useNuxtApp().$api as typeof $fetch, ...callerOptions, }))::important 此处必须使用函数签名覆盖模式。原因在于useNuxtApp()需要在 setup 上下文即组合式函数被调用的地方执行而不是在模块顶层作用域执行——模块顶层并不存在可用的 Nuxt 实例。传入函数后useNuxtApp()被推迟到每次调用useAPI时才求值从而拿到正确的实例。而...callerOptions的展开则保证把调用方的实时选项也一并纳入。如果你倾向于低层控制也可以在插件中创建自定义$fetch实例后再与createUseFetch或useAsyncData组合——完整的两步式配方含通过nuxtApp.runWithContext处理 401 跳转见 custom-usefetch.md 的 “Recipe: Custom$fetchInstance” 一节。底层实现原理自动 key 与工厂合并理解createUseFetch的核心在于看透它并非“包了一层 default options 的普通函数”而是整套 keyed function factory 编译管线的入口。结合源码可以梳理出三层机制1. 去重 key 的自动注入。派生出的组合式函数在运行时基于调用点信息计算 keykey $f hashKey([autoKey, request, ...generateOptionSegments(fetchOptions)])fetch.ts。其中autoKey由编译器按调用点位置注入generateOptionSegments会把method、baseURL、query/params、body等参与序列化见 fetch.ts。这意味着同一派生组合式函数在不同组件中的调用会得到不同 key、各自发起请求相同调用点会共享状态。需要跨组件共享数据时仍需显式传入相同的key。2. 工厂选项的两段合并。运行时先把“工厂选项”解析出来——函数模式则先调用工厂取得返回值随后按默认/覆盖两种顺序与调用方选项合并再按职责拆分server、lazy、transform、getCachedData、enabled、serialize等交给useAsyncData其余baseURL、headers、query等进入 ofetch 请求配置fetch.ts。3.useFetch本身就是这个工厂的产物。源码末尾的useFetch与useLazyFetch都经由createUseFetch.__nuxt_factory()后者额外注入了lazy: true与内部函数名创建fetch.ts。换句话说createUseFetch是比useFetch更底层的原语——这也是为什么官方文档在 use-fetch.md 中提示不要自行声明名为useFetch的函数需要自定义变体时请使用createUseFetch。实战配方带鉴权与 401 处理的 API 客户端把上述能力组合起来一个典型的“API 客户端”配方如下完整出处见 custom-usefetch.mdexport const useAPI createUseFetch({ baseURL: https://api.nuxt.com, onRequest ({ options }) { const { session } useUserSession() if (session.value?.token) { options.headers.set(Authorization, Bearer ${session.value.token}) } }, async onResponseError ({ response }) { if (response.status 401) { await navigateTo(/login) } }, })此后应用内的所有请求都自动携带鉴权头并统一处理 401script setup langts const { data: profile } await useAPI(/me) const { data: orders } await useAPI(/orders) /script当你需要对接多个不同的后端不同的 baseURL、不同的认证方案时可以为每个后端各创建一份如useAPI、useAdminAPI的派生组合式函数实现按 API 维度的请求配置隔离。延伸阅读useFetch完整选项与返回值参考useAsyncData参考姊妹宏createUseAsyncDataCustom useFetch in Nuxt 实战食谱useNuxtApp源码fetch.ts、keyed-function-factories 编译器插件、defineKeyedFunctionFactory测试keyed-function-factories.test.ts【免费下载链接】nuxtthe full-stack Vue framework项目地址: https://gitcode.com/GitHub_Trending/nu/nuxt创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表