资讯动态

TanStack Query 的 Lit 适配器 @tanstack/lit-query 完整 API 参考:响应式控制器、QueryClientProvider 与客户端解析机制

发布时间:2026/9/8 21:16:50 来源:尧图企业网站定制
TanStack Query 的 Lit 适配器 tanstack/lit-query 完整 API 参考响应式控制器、QueryClientProvider 与客户端解析机制【免费下载链接】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/lit-query的 API 参考目录docs/framework/lit/reference/index.md为骨架完整梳理该 Lit 适配器的全部导出1 个类、1 个变量、14 个函数与 24 个类型别名。结合 packages/lit-query 的源码实现解释控制器如何通过 Lit Reactive Controller 机制订阅查询、QueryClientProvider如何经 Lit context 分发QueryClient以及客户端解析、缓存状态辅助函数等细节帮助你在 Lit Web Components 中正确地做异步状态管理与数据获取。参考文档总览与 API 全景tanstack/lit-query是 TanStack Query 的 Lit 适配器当前仓库版本为 0.2.20见 package.json。包入口 src/index.ts 首先执行export * from tanstack/query-core因此QueryClient、InfiniteData等核心类型与类可以直接从tanstack/lit-query导入。参考索引将导出分为四类分类导出项参考页ClassesQueryClientProviderclasses/QueryClientProvider.mdVariablesqueryClientContextvariables/queryClientContext.mdFunctions控制器createQueryController、createInfiniteQueryController、createMutationController、createQueriesController见下文Functions选项构建器queryOptions、infiniteQueryOptions、mutationOptionsqueryOptions.md 等Functions客户端辅助useQueryClient、resolveQueryClient、getDefaultQueryClient、registerDefaultQueryClient、unregisterDefaultQueryClientuseQueryClient.md 等Functions缓存状态useIsFetching、useIsMutating、useMutationStateuseIsFetching.md 等所有控制器创建函数共享同一个签名形态function createXxxController(host, options, queryClient?): XxxResultAccessor // host: ReactiveControllerHost —— 承载控制器生命周期的 Lit 宿主 // options: AccessorXxxOptions —— 直接传选项对象或传一个 getter // queryClient?: QueryClient —— 可选显式客户端省略时从最近的 QueryClientProvider 解析返回的 accessor 既可调用this.todos()也可读current属性this.todos.current这是 Lit 适配器统一的读取约定详见 accessor.ts。客户端供给QueryClientProvider 与 queryClientContext参考索引中唯一的类是 QueryClientProvider唯一的变量是 queryClientContext。二者共同构成 Lit 场景下“把QueryClient交给组件树”的机制。QueryClientProvider 的关键约束从 QueryClientProvider.ts 源码可以看到几个必须遵守的约束client是属性而非 attributestatic properties { client: { attribute: false } }。在 Lit 模板中必须用属性绑定.client${queryClient}而不是字符串属性。包不会自动注册自定义元素。应用必须自行customElements.define该类或其子类官方 JSDoc 明确要求这一点。无客户端时快速失败provider 在无client的情况下连接、或已连接的 provider 被清空client时会抛出createMissingQueryClientError()。连接时会client.mount()并调用registerDefaultQueryClient(client)断开时client.unmount()并unregisterDefaultQueryClient(client)见 QueryClientProvider.ts#L140-L165。两种推荐写法来自参考页示例// 写法一子类注入适合需要固定 client 的场景 import { html, LitElement } from lit import { QueryClient, QueryClientProvider } from tanstack/lit-query const queryClient new QueryClient() class AppQueryProvider extends QueryClientProvider { constructor() { super() this.client queryClient } } customElements.define(app-query-provider, AppQueryProvider) class AppRoot extends LitElement { render() { return htmlapp-query-providertodos-view/todos-view/app-query-provider } }// 写法二直接注册基类模板中属性绑定 import { html } from lit import { QueryClient, QueryClientProvider } from tanstack/lit-query const queryClient new QueryClient() customElements.define(query-client-provider, QueryClientProvider) const view html query-client-provider .client${queryClient} todos-view/todos-view /query-client-provider queryClientContextcontext.ts 中定义了上下文键export const queryClientContext createContextQueryClient( Symbol.for(tanstack-query-client), )文档说明大多数应用应使用QueryClientProvider而不是直接操作这个 context控制器内部通过它完成客户端的查找与订阅。四个控制器创建函数控制器是 Lit Query 的核心 API它们把ReactiveControllerHost通常是LitElement挂接到查询/变更观察者上宿主连接、更新、断开时自动完成订阅、重读选项与清理。createQueryController签名与定义位置createQueryController.ts#L355function createQueryControllerTQueryFnData, TError, TData, TQueryData, TQueryKey( host: ReactiveControllerHost, options: AccessorCreateQueryOptionsTQueryFnData, TError, TData, TQueryData, TQueryKey, queryClient?: QueryClient, ): QueryResultAccessorTData, TError类型参数默认值TQueryFnData unknown、TError Error、TData TQueryFnData、TQueryKey extends readonly unknown[]。options既可以是静态的QueryObserverOptions也可以是 getter 函数——函数形式会在宿主每次 update 时被重新读取见onHostUpdate实现createQueryController.ts#L153-L159因此queryKey等可以跟随响应式宿主状态。省略queryClient时控制器从最近的已连接QueryClientProvider解析客户端。返回的QueryResultAccessor额外暴露refetch、suspense返回PromiseQueryObserverResult数据过期时会先乐观取数、destroy把控制器从宿主移除并取消订阅三个方法。参考页示例functions/createQueryController.mdimport { LitElement, html } from lit import { createQueryController } from tanstack/lit-query class TodosView extends LitElement { private readonly todos createQueryController(this, { queryKey: [todos], queryFn: async () fetch(/api/todos).then((r) r.json()), }) render() { const query this.todos() if (query.isPending) return htmlLoading... if (query.isError) return htmlError return htmlul${query.data.map((todo) htmlli${todo.title}/li)}/ul } }createInfiniteQueryController签名createInfiniteQueryController.ts#L402function createInfiniteQueryControllerTQueryFnData, TError, TData, TQueryKey, TPageParam( host, options: AccessorCreateInfiniteQueryOptions..., queryClient?, ): InfiniteQueryResultAccessorTData, TError其中TData默认为InfiniteDataTQueryFnData, unknown。返回的 accessor 在current与调用形式之外额外暴露refetch、fetchNextPage、fetchPreviousPage和destroy选项是函数时同样会在宿主更新时重读。示例import { LitElement, html } from lit import { createInfiniteQueryController } from tanstack/lit-query class ProjectsView extends LitElement { private readonly projects createInfiniteQueryController(this, { queryKey: [projects], queryFn: ({ pageParam }) fetchProjects(pageParam), initialPageParam: 0, getNextPageParam: (lastPage) lastPage.nextCursor, }) render() { const query this.projects() return html button ?disabled${!query.hasNextPage} click${() this.projects.fetchNextPage()} Load more /button } }createMutationController签名createMutationController.ts#L340function createMutationControllerTData, TError, TVariables, TOnMutateResult( host, options: AccessorCreateMutationOptions..., queryClient?, ): MutationResultAccessorTData, TError, TVariables, TOnMutateResult类型参数默认值TData unknown、TError Error、TVariables void、TOnMutateResult unknown。返回的 accessor 额外暴露mutate、mutateAsync、reset与destroy。示例import { LitElement, html } from lit import { createMutationController } from tanstack/lit-query class AddTodoForm extends LitElement { private readonly addTodo createMutationController(this, { mutationFn: (title: string) fetch(/api/todos, { method: POST, body: JSON.stringify({ title }) }), }) render() { const mutation this.addTodo() return html button ?disabled${mutation.isPending} click${() this.addTodo.mutate(Ship docs)} Add todo /button } }createQueriesController签名createQueriesController.ts#L701function createQueriesControllerTQueryOptions extends any[], TCombinedResult( host, options: AccessorCreateQueriesControllerOptionsTQueryOptions, TCombinedResult, queryClient?, ): QueriesResultAccessorTCombinedResult用于一次订阅多个查询。options与options.queries都支持 getter 形式从而让查询列表跟随宿主状态。返回 accessor 暴露current与destroy传入combine时读取到的结果是combine的返回值否则是各查询结果的数组。示例import { LitElement, html } from lit import { createQueriesController } from tanstack/lit-query class DashboardView extends LitElement { private readonly dashboard createQueriesController(this, { queries: [ { queryKey: [stats], queryFn: fetchStats }, { queryKey: [projects], queryFn: fetchProjects }, ], combine: ([stats, projects]) ({ stats: stats.data, projects: projects.data ?? [], isPending: stats.isPending || projects.isPending, }), }) render() { const dashboard this.dashboard() return htmlpProjects: ${dashboard.projects.length}/p } }Accessor统一的响应式结果读取约定参考索引中的 Accessor 与 ValueAccessor 两个类型别名定义了适配器的两套“函数式取值”约定实现在 accessor.ts// 输入侧静态值或零参 getter export type AccessorT T | (() T) export function readAccessorT(value: AccessorT): T { return typeof value function ? (value as () T)() : value } // 输出侧可调用且带 current 属性 export type ValueAccessorT (() T) { readonly current: T }也就是说所有create*Controller与缓存状态辅助函数都遵循同一套 API 形状调用this.todos()或读this.todos.current都得到最新结果而options/filters等入参都可以是 gettergetter 内部可以安全引用宿主的响应式属性。选项构建器与缓存状态辅助函数queryOptions / infiniteQueryOptions / mutationOptions参考页 queryOptions.md、infiniteQueryOptions.md、mutationOptions.md 分别对应 queryOptions.ts、infiniteQueryOptions.ts、mutationOptions.ts 三个模块均由 src/index.ts#L60-L63 导出。它们把查询/变更选项构建成类型化的 options 对象可以集中定义后传给对应的create*Controller从src/index.ts的再导出还能看到与queryOptions.ts关联的三个约束类型 DefinedInitialDataOptions、UndefinedInitialDataOptions、UnusedSkipTokenOptions参考索引中列出的类型别名。useIsFetching / useIsMutating / useMutationState三个缓存状态辅助函数都遵循相同的签名形态(host, filters?, queryClient?)创建订阅 QueryCache/MutationCache 的响应式控制器filters是Accessor函数形式时随宿主更新重读。以 useIsFetching 为例useIsFetching.ts#L147function useIsFetching(host, filters?: AccessorQueryFilters, queryClient?): IsFetchingAccessorimport { LitElement, html } from lit import { useIsFetching } from tanstack/lit-query class TodosStatus extends LitElement { private readonly todosFetching useIsFetching(this, { queryKey: [todos], }) render() { return htmlspan${this.todosFetching()} active todo fetches/span } }对应的返回类型别名为 IsFetchingAccessor、IsMutatingAccessor、MutationStateAccessoruseMutationState 的过滤条件类型为 MutationStateOptions。相关行为由 counters-and-state.test.ts 覆盖。客户端辅助函数参考索引中的 5 个 context 相关函数实现在 context.ts函数行为registerDefaultQueryClient以引用计数方式内部registeredClientsMap把客户端登记为进程级 fallbackQueryClientProvider连接时自动调用unregisterDefaultQueryClient释放一次登记计数归零后从默认客户端链表中移除context.ts#L45-L63getDefaultQueryClient仅当注册客户端数为 1 时返回它否则0 个或多个返回undefineduseQueryClient在控制器之外获取客户端无客户端时抛No QueryClient available. Pass one explicitly or render within QueryClientProvider.多个客户端挂载时抛Multiple QueryClients are mounted. Pass one explicitly instead of relying on global QueryClient helpers.context.ts#L15-L18resolveQueryClientexplicit ?? useQueryClient()的便捷封装即显式客户端优先、否则回退到默认解析从源码结构看这套机制让 provider 连接期间“全局恰好一个客户端”的假设可被精确判定引用计数使多个 provider 挂载同一客户端不会互相干扰而挂载不同客户端则会令全局 helper 变为“歧义”而抛错。类型别名一览参考索引全量docs/framework/lit/reference/index.md 列出的 24 个类型别名按用途分组如下分组类型别名通用读取约定Accessor、ValueAccessor创建入参CreateQueryOptions、CreateInfiniteQueryOptions、CreateMutationOptions、CreateQueriesControllerOptions、CreateQueriesInput、MutationStateOptions控制器选项与结果QueryControllerOptions、QueryControllerResult、InfiniteQueryControllerOptions、MutationControllerOptions、MutationControllerResult、QueriesControllerOptions返回 accessorQueryResultAccessor、InfiniteQueryResultAccessor、MutationResultAccessor、QueriesResultAccessor、IsFetchingAccessor、IsMutatingAccessor、MutationStateAccessor选项构建器约束DefinedInitialDataOptions、UndefinedInitialDataOptions、UnusedSkipTokenOptions其中QueryResultAccessorTData, TError在源码中的精确定义是ValueAccessorQueryObserverResultTData, TError加上refetch/suspense/destroy三个方法createQueryController.ts#L42-L51可以作为理解其余 accessor 类型的模板。内部机制BaseController 的客户端解析与更新调度所有控制器都继承抽象基类 BaseController理解了它就能解释参考文档中“省略 queryClient 时从最近的 QueryClientProvider 解析”“options 是函数时会在宿主更新时重读”这两句话的底层行为。客户端解析状态机BaseController维护一个四态的解析状态BaseController.ts#L9-L13type QueryClientResolutionState | pre-connect // 尚未连接或已断开 | awaiting-context // 等待 Lit context 中的 QueryClientProvider | bound // 已拿到客户端显式传入或 context 送达 | missing // context 送达但未提供客户端关键流程BaseController.ts#L42-L102hostConnected()显式客户端直接进入bound否则进入awaiting-context并通过dispatchContextRequest向宿主派发ContextEventlit/context订阅queryClientContext。微任务中若 context 未送达任何客户端状态落为missing此后current访问与getQueryClient()都会抛出createMissingQueryClientError()。onConnected被queueMicrotask延迟调用避免在“宿主已连接时执行addController”的场景下如字段初始化发生在willUpdate期间子类状态尚未就绪就被访问——源码注释明确说明了这一防御动机BaseController.ts#L57-L66。hostDisconnected()断开时撤销 context 订阅、递增连接尝试计数子类执行清理。destroy()幂等销毁从宿主removeController(this)并把解析状态重置回pre-connectBaseController.ts#L104-L121。更新批处理与客户端切换setResult用Object.is去重结果不变不触发宿主更新变化时用queueMicrotask批量调度一次host.requestUpdate()BaseController.ts#L136-L171。当 provider 换绑了另一个客户端时context 订阅回调检测到contextClient变化先queueUpdate()再queueQueryClientChanged()最终触发子类onQueryClientChanged()。以QueryController为例它会syncClient()销毁旧 observer、用新客户端重建QueryObserver并取乐观结果、重读 options 并重新订阅createQueryController.ts#L161-L249行为由 client-switch-controllers.test.ts 验证。无客户端时的降级结果QueryController在未绑定客户端前会以一份手工构造的createPendingQueryResult()作为初始结果status: pending、isPending: true、isStale: truerefetch被替换为拒绝并抛出 missing-client 错误的 Promise见 createQueryController.ts#L53-L88。这解释了为什么组件在 provider 未就绪时读到的是“pending”而不是抛错——只有访问current状态为missing时或调用getQueryClient()才会真正抛出。乐观结果标记defaultOptions()在取回默认化选项后显式打上_optimisticResults optimistic标记createQueryController.ts#L300-L312使 observer 在未挂载状态下也能返回带refetch等方法的乐观结果suspense()正是基于getOptimisticResultfetchOptimistic实现createQueryController.ts#L186-L199供 SSR 等需要“取数即得结果”的场景使用。快速上手把参考 API 串起来综合以上 API一个最小可运行示例源自 docs/framework/lit/quick-start.md完整可运行工程见 examples/lit/basicimport { LitElement, html } from lit import { QueryClient, QueryClientProvider, createMutationController, createQueryController, } from tanstack/lit-query import { addTodo, getTodos } from ./api const queryClient new QueryClient() class AppQueryProvider extends QueryClientProvider { constructor() { super() this.client queryClient } } customElements.define(app-query-provider, AppQueryProvider) class TodosView extends LitElement { private readonly todos createQueryController(this, { queryKey: [todos], queryFn: getTodos, }) private readonly createTodo createMutationController(this, { mutationFn: addTodo, onSuccess: async () { await queryClient.invalidateQueries({ queryKey: [todos] }) }, }) render() { const query this.todos() const mutation this.createTodo() if (query.isPending) return htmlLoading... if (query.isError) return htmlError: ${query.error.message} return html ul ${query.data.map((todo) htmlli${todo.title}/li)} /ul button ?disabled${mutation.isPending} click${() this.createTodo.mutate({ title: Write Lit docs })} Add Todo /button } } customElements.define(todos-view, TodosView)app-query-provider todos-view/todos-view /app-query-provider要点控制器以this为宿主创建因为LitElement本身就是ReactiveControllerHostLit Query 借助宿主生命周期完成订阅、请求更新与断连清理。测试覆盖与延伸阅读包内测试位于 packages/lit-query/src/tests/与参考 API 一一对应query-controller.test.ts、infinite-and-options.test.ts、mutation-controller.test.ts、queries-controller.test.ts、client-switch-controllers.test.ts、context-provider.test.ts、counters-and-state.test.ts、type-inference.test.ts以及 base-controller.test.ts。若需要更细的使用指导可继续阅读 Lit 框架下的指南queries.md、mutations.md、infinite-queries.md、parallel-queries.md、query-invalidation.md、ssr.md了解 React Query 用户如何迁移心智模型可参考 reactive-controllers-vs-hooks.md。可运行示例还有 examples/lit/pagination 与 examples/lit/ssr。【免费下载链接】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),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价