ARTICLE DETAIL

资讯详情

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

TanStack Query Angular 默认 queryFn 实战:用 defaultOptions 为 injectQuery 省去逐条声明

TanStack Query Angular 默认 queryFn 实战:用 defaultOptions 为 injectQuery 省去逐条声明 TanStack Query Angular 默认 queryFn 实战用 defaultOptions 为 injectQuery 省去逐条声明【免费下载链接】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本篇技术指南基于 TanStack QueryAngular 适配器 tanstack/angular-query-experimental的 default-query-function 指南讲解如何通过QueryClient的defaultOptions.queries.queryFn注册一个全局默认查询函数从而让injectQuery只需传入queryKey即可完成数据获取。读完本文你将掌握完整可运行的示例写法并能在源码层面理解默认值是如何与每次调用的 options 合并、覆盖的。核心思路把「怎么取数据」声明一次把「取什么」留给组件在典型的 REST 应用里绝大多数查询的差异只在于 URL 路径即queryKey而请求方式axios/fetch 实例、认证头、错误归一化、数据解包是高度一致的。如果每个组件都写一遍queryFn: () axios.get(...).then(r r.data)会产生大量重复代码且请求层难以统一替换比如全局换 baseURL、统一注入 token。TanStack Query 的解法就是「默认查询函数」Default Query Function在创建QueryClient时通过defaultOptions.queries.queryFn提供一个QueryFunction之后所有查询在自身未显式声明queryFn时都会回落到这个默认实现并且queryFn能收到完整的QueryFunctionContext含queryKey因此可以根据 key 动态拼接请求路径。完整示例从定义到组件使用下面完整继承官方指南中的示例代码覆盖「定义默认函数 → 注册到客户端 → 接入 Angular 应用 → 组件中只传 key」四个环节。定义并注册 defaultQueryFn// Define a default query function that will receive the query key const defaultQueryFn: QueryFunction async ({ queryKey }) { const { data } await axios.get( https://jsonplaceholder.typicode.com${queryKey[0]}, ) return data } // provide the default query function to your app with defaultOptions const queryClient new QueryClient({ defaultOptions: { queries: { queryFn: defaultQueryFn, }, }, })要点说明默认函数签名是QueryFunction接收一个上下文对象其中最常用的是queryKey。示例中把queryKey[0]直接当作 API 路径如/posts、/posts/1拼接到 jsonplaceholder 的 baseURL 上这是一种「key 即路由」的约定defaultOptions.queries是全局查询默认值的挂载点除了queryFn还可以放staleTime、retry等本文聚焦queryFnQueryClient构造器会把传入的defaultOptions保存下来config.defaultOptions || {}后续所有defaultQueryOptions(...)调用都从这里读取见 QueryClient 构造函数。把客户端接入 Angular 应用bootstrapApplication(MyAppComponent, { providers: [provideTanStackQuery(queryClient)], })provideTanStackQuery内部通过provideQueryClient把QueryClient注册为可注入的单例并在 injector 销毁时调用client.unmount()、创建时调用client.mount()源码见 providers.ts。它也支持传入InjectionToken以支持懒加载路由单独挂载 Query并可通过withDevtools()启用开发者工具文档见 providers.ts 的 JSDoc。组件中只传 queryKeyexport class PostsComponent { // All you have to do now is pass a key! postsQuery injectQueryArrayPost(() ({ queryKey: [/posts], })) // ... } export class PostComponent { // You can even leave out the queryFn and just go straight into options postQuery injectQueryPost(() ({ enabled: this.postIdSignal() 0, queryKey: [/posts/${this.postIdSignal()}], })) // ... }两个细节值得注意injectQuery接收一个 options 函数() options而非字面量对象。从 createBaseQuery.ts 的注释可以确认这是刻意设计options 被包在函数里后内部嵌入的 signal 表达式如this.postIdSignal()才能被 Angular 的响应式系统追踪signal 变化时默认选项和 observer 才会自动重算。queryFn被整体省略后类型系统依然完整。injectQuery的泛型参数ArrayPost/Post直接决定了返回值信号的类型无需本地声明返回Promise的函数query-options.ts中的UnusedSkipTokenOptions与DefinedInitialDataOptions等类型正是把queryFn声明为可选字段的依据见 query-options.ts。源码层面默认 queryFn 是如何生效的第一步createBaseQuery 用 computed 应用全局默认值injectQuery与injectInfiniteQuery共享同一个底层工厂createBaseQuery。其中defaultedOptionsSignal是一个computed每次求值都会调用queryClient.defaultQueryOptions(optionsFn())把组件传入的 options 与全局默认值合并const defaultedOptionsSignal computed(() { const defaultedOptions queryClient.defaultQueryOptions(optionsFn()) defaultedOptions._optimisticResults isRestoring() ? isRestoring : optimistic return defaultedOptions })见 create-base-query.ts。由于它是computed当optionsFn()内引用的 signal例如postIdSignal变化时合并结果会重新计算enabled、queryKey等也随之更新。第二步QueryClient.defaultQueryOptions 的合并顺序合并逻辑在 QueryClient.defaultQueryOptions 中核心是三段展开const defaultedOptions { ...this.#defaultOptions.queries, // ① 全局默认值含我们的 defaultQueryFn ...this.getQueryDefaults(options.queryKey), // ② 按 key 前缀匹配的 setQueryDefaults ...options, // ③ 本次调用显式传入的 options _defaulted: true, }从源码结构看优先级由低到高是defaultOptions.queries构造QueryClient时传入全局生效setQueryDefaults(queryKey, options)注册的按 key 前缀匹配的默认值getQueryDefaults通过partialMatchKey做前缀匹配见 queryClient.ts每次injectQuery传入的 options可以覆盖默认queryFn或任何其它字段。这意味着全局注册defaultQueryFn之后某个特殊查询仍可在 options 里写自己的queryFn覆盖它也可以只对/posts/*这一族 key 用setQueryDefaults提供局部默认值而不影响其它 key。方法还会补全若干派生默认值如refetchOnReconnect、throwOnError、networkMode并对skipToken做enabled false的转换见 queryClient.ts。带_defaulted标记的对象会被直接短路返回避免重复合并。第三步Query 执行时如何找到 queryFn真正发起请求前Query会在this.options.queryFn缺失时从已订阅的 observer 中找出携带queryFn的那个作为兜底defaultOptions.queries.queryFn正是在合并阶段被放进了 observer optionsif (!this.options.queryFn) { const observer this.observers.find((x) x.options.queryFn)见 query.ts。随后通过ensureQueryFn(this.options, fetchOptions)解析出最终函数并以其构造QueryFunctionContext执行query.ts。这条链路解释了为什么「组件里不写 queryFn」仍然能发起请求默认值在 observer 合并期就已经挂到 options 上执行期只是读取。默认值、queryOptions 与类型安全如果你偏好把查询配置抽到组件外部复用可以用同包的queryOptions帮助函数query-options.ts。它本身只是恒等函数价值在于三个重载为queryKey打上queryFn的数据类型标签const { queryKey } queryOptions({ queryKey: [key], queryFn: () Promise.resolve(5), // ^? Promisenumber })打上标签后queryClient.getQueryData(queryKey)的返回值类型就是number | undefined而不是unknown。把queryOptions与全局defaultQueryFn结合时抽出的配置可以只含queryKey数据获取细节全部交给默认函数同时保持端到端的类型推断。实践建议与边界结合仓库实现给出几条落地时的注意点让 key 成为「请求路径」的前提是请求层可控。示例中queryKey[0]直接拼 URL适合 REST 且路径结构稳定的 API对 GraphQL 或非路径型 key默认函数应按 key 结构分派从queryKey首元素判断资源类型再选择对应请求逻辑。默认函数里做集中式错误/响应归一化。既然queryFn是全局单点axios 拦截器式的解包return data、错误映射都适合放在这里各组件无需感知。局部覆盖优于复制粘贴个别查询的取数逻辑确实不同时在该次injectQuery的 options 中显式写queryFn即可合并顺序的第 ③ 层不要为此拆出第二个QueryClientprovideQueryClient的文档注释也说明它更适用于应用局部或单元测试场景见 providers.ts。响应式依赖依赖 options 函数。默认queryFn的注册是「应用级静态配置」而enabled、queryKey这类与 signal 相关的字段必须在 options 函数内引用 signal如示例的this.postIdSignal() 0才会随信号更新——这是 createBaseQuery.ts 注释中强调的行为。适用前提defaultOptions.queries.queryFn由 query-core 提供Angular 侧经由tanstack/angular-query-experimental的provideTanStackQuery注入客户端后自动生效版本行为以本仓库当前 query-core 源码 与 Angular 适配器源码 为准。小结默认 queryFn 模式把「如何请求」从 N 个组件收敛到 1 处QueryClient配置defaultQueryFn接收queryKey动态构造请求provideTanStackQuery(queryClient)完成应用级注入injectQuery(() ({ queryKey: [...] }))则让组件代码退化为「声明 key 泛型类型」。源码链路上computed包裹的defaultQueryOptions合并全局默认 → 按 key 前缀默认 → 调用方 options与Query执行期的queryFn兜底查找共同保证了这套省略写法在响应式更新下的正确性。仓库中的 Angular 示例应用bootstrapApplicationappConfig提供provideTanStackQuery可直接作为搭建起点。【免费下载链接】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),仅供参考
返回列表