指南:注入 QueryClient 与自定义上下文键)
Vue Query 自定义客户端Custom Client指南注入 QueryClient 与自定义上下文键【免费下载链接】query Powerful asynchronous state management, server-state utilities and data fetching for the web. TS/JS, React Query, Solid Query, Svelte Query and Vue Query.项目地址: https://gitcode.com/GitHub_Trending/qu/queryVue Query 通过VueQueryPlugin插件将QueryClient注入到 Vue 应用的上下文中本指南讲解两种注入方式——直接传入QueryClientConfig配置对象由插件内部创建实例或预先创建好QueryClient实例再传入——以及如何自定义客户端在上下文中的键名key从而支持多个 Vue 应用尤其是 Vue 2 场景在同一页面共存而互不冲突。读完本文你将掌握自定义客户端注入、自定义上下文键以及useQueryClient()取回客户端的完整实战方案。为什么需要自定义 ClientVue Query 默认由VueQueryPlugin在安装时自动创建并注入一个QueryClient。但存在一些场景默认行为无法满足需求你需要在安装插件之前创建QueryClient以便把它传递给其他不依赖 Vue 上下文的库例如路由守卫、独立的工具函数、测试工具等你希望为不同应用或不同模块复用、共享同一个客户端实例你需要在同一个页面中挂载多个 Vue 应用尤其是 Vue 2它们的客户端键名需要隔离避免上下文冲突。为此VueQueryPlugin的插件选项被设计为两种形态的组合要么传入queryClientConfig配置对象要么传入queryClient实例。从源码看vueQueryPlugin.ts 中定义了ConfigOptions与ClientOptions两个接口并合并为联合类型VueQueryPluginOptionsinterface ConfigOptions extends CommonOptions { queryClientConfig?: QueryClientConfig } interface ClientOptions extends CommonOptions { queryClient?: QueryClient } export type VueQueryPluginOptions ConfigOptions | ClientOptions在 安装逻辑 中插件会优先检查是否存在queryClient属性存在则直接使用该实例否则读取queryClientConfig并内部new QueryClient(clientConfig)if (queryClient in options options.queryClient) { client options.queryClient } else { const clientConfig queryClientConfig in options ? options.queryClientConfig : undefined client new QueryClient(clientConfig) }QueryClientConfig的定义位于 types.ts包含queryCache、mutationCache与defaultOptions三个字段export interface QueryClientConfig { queryCache?: QueryCache mutationCache?: MutationCache defaultOptions?: DefaultOptions }其中defaultOptions又分为queries、mutations、hydrate、dehydrate四组默认配置详见 DefaultOptions 定义。方式一通过 queryClientConfig 自动创建当你只需要对默认客户端做配置、无需在插件外部提前持有实例时直接传入queryClientConfig即可。插件会在安装过程中内部创建QueryClient并提供给 Vue 上下文const vueQueryPluginOptions: VueQueryPluginOptions { queryClientConfig: { defaultOptions: { queries: { staleTime: 3600 } }, }, } app.use(VueQueryPlugin, vueQueryPluginOptions)上面的示例将全局查询的默认staleTime设置为 3600 毫秒此后所有通过useQuery创建的查询在 3.6 秒内都会被判定为新鲜fresh不会在重复挂载时立刻重新请求。方式二预先创建 QueryClient 实例当需要把客户端与 Vue 上下文解耦、供其他库或模块提前使用时先手动创建实例再以queryClient字段传入const myClient new QueryClient(queryClientConfig) const vueQueryPluginOptions: VueQueryPluginOptions { queryClient: myClient, } app.use(VueQueryPlugin, vueQueryPluginOptions)myClient既可以通过new QueryClient()从零创建也可以基于某个已有的配置对象queryClientConfig创建。注意两种选项是互斥的queryClientConfig与queryClient同时提供时从 安装逻辑 可以推断插件会优先采用queryClient实例。客户端生命周期管理从 vueQueryPlugin.ts 可以看出插件安装时还会负责客户端的生命周期非服务端环境下会调用client.mount()启动客户端支持clientPersister持久化回调恢复中置isRestoring完成后再触发clientPersisterOnSuccess应用卸载app.unmount或app.onUnmount时统一执行client.unmount()与持久化卸载清理。自定义上下文键Custom Context KeyQueryClient默认被注入到 Vue 上下文键VUE_QUERY_CLIENT下。你可以通过queryClientKey选项自定义键名后缀这在同一页面同时运行多个 Vue 应用尤其是 Vue 2时非常有用可以避免多个应用之间的上下文命名冲突。只传键名、使用默认创建的客户端const vueQueryPluginOptions: VueQueryPluginOptions { queryClientKey: Foo, } app.use(VueQueryPlugin, vueQueryPluginOptions)同时传自定义客户端与自定义键名const myClient new QueryClient(queryClientConfig) const vueQueryPluginOptions: VueQueryPluginOptions { queryClient: myClient, queryClientKey: Foo, } app.use(VueQueryPlugin, vueQueryPluginOptions)键名的拼接规则从 utils.ts 的源码可以看到键名拼接的具体实现export const VUE_QUERY_CLIENT VUE_QUERY_CLIENT export function getClientKey(key?: string) { const suffix key ? :${key} : return ${VUE_QUERY_CLIENT}${suffix} }自定义键会以后缀的形式与默认键组合无需使用者手动处理。例如传入queryClientKey: Foo实际注入的上下文键为const vueQueryPluginOptions: VueQueryPluginOptions { queryClientKey: Foo, } app.use(VueQueryPlugin, vueQueryPluginOptions) // - VUE_QUERY_CLIENT:Foo使用自定义键取回客户端要让使用自定义键的应用能正确取回对应的客户端需要在查询选项中同步提供queryClientKeyuseQuery({ queryKey: [query1], queryFn: fetcher, queryClientKey: foo, })这里需要注意大小写插件选项中的属性名为queryClientKey驼峰组合后得到的是VUE_QUERY_CLIENT:foo。在需要手动获取客户端时也可以直接调用useQueryClient(id)并传入与queryClientKey相同的值。从 useQueryClient.ts 的实现可以看到useQueryClient同样通过getClientKey(id)拼接键名后再injectexport function useQueryClient(id ): QueryClient { // ensures that inject() can be used if (!hasInjectionContext()) { throw new Error( vue-query hooks can only be used inside setup() function or functions that support injection context., ) } const key getClientKey(id) const queryClient injectQueryClient(key) if (!queryClient) { throw new Error( No queryClient found in Vue context, use VueQueryPlugin to properly initialize the library., ) } return queryClient }即useQueryClient()默认注入VUE_QUERY_CLIENT而useQueryClient(foo)注入VUE_QUERY_CLIENT:foo与插件侧的自定义键严格对应。该行为在测试 useQueryClient.test.ts 中得到了验证传入foo时inject被调用参数为${VUE_QUERY_CLIENT}:${queryClientKey}。源码中的上下文注入细节插件在不同 Vue 版本下的注入方式略有差异见 vueQueryPlugin.tsVue 3 及兼容环境调用app.provide(clientKey, client)Vue 2通过 vue-demi 兼容使用全局 mixin 的beforeCreate钩子将客户端写入组件实例的_provided对象从而模拟 provide/inject 行为。此外useQueryClient会先检查hasInjectionContext()若在setup()之外调用会直接抛出错误这一边界行为同样有测试覆盖useQueryClient.test.ts。内部实现验证围绕自定义客户端vue-query包中还有一组配套测试可以佐证上述行为vueQueryPlugin.test.ts覆盖VueQueryPlugin.install传入queryClientKey如CUSTOM时的安装行为useQueryClient.test.ts覆盖默认键注入、自定义键后缀拼接、未安装插件时报错、setup()外调用报错等场景。同时从 useBaseQuery.ts、useMutation.ts、useQueries.ts 等 hook 的实现可以看出绝大多数组合式函数都遵循同一模式优先使用选项里显式传入的queryClient否则回退到useQueryClient()从上下文获取。这意味着自定义客户端一旦注入成功所有查询、变更、无限查询等 hook 都会自动感知并使用它。总结场景推荐配置只需调整默认客户端参数queryClientConfig: { defaultOptions: {...} }需要提前创建、共享或注入外部客户端queryClient: myClient多应用/多客户端共存尤其 Vue 2queryClientKey: Foo并在查询选项中同步传递手动取回客户端useQueryClient()或useQueryClient(foo)自定义客户端Custom Client是 Vue Query 灵活性的核心入口queryClientConfig与queryClient分别对应“由插件托管”和“由应用托管”两种客户端生命周期queryClientKey则通过${VUE_QUERY_CLIENT}:${key}的后缀拼接规则为多实例共存提供命名空间隔离。合理组合这三个选项即可在任意复杂度的 Vue 应用中精确控制查询状态的注入、共享与隔离。【免费下载链接】query Powerful asynchronous state management, server-state utilities and data fetching for the web. TS/JS, React Query, Solid Query, Svelte Query and Vue Query.项目地址: https://gitcode.com/GitHub_Trending/qu/query创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考