TanStack Lit Query 的 Accessor 类型:让查询选项同时支持静态值与响应式 Getter

发布时间:2026/9/8 21:24:59

TanStack Lit Query 的 Accessor 类型:让查询选项同时支持静态值与响应式 Getter TanStack Lit Query 的 Accessor 类型让查询选项同时支持静态值与响应式 Getter【免费下载链接】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的核心类型别名AccessorT展开它是 Lit Query 全部控制器 API 的响应式入口允许把查询/变更mutation选项以静态对象或零参 getter 两种形式传入。读完本文你将理解Accessor的定义与readAccessor读取机制、它在控制器生命周期中何时被求值的底层实现以及如何在 Lit 组件中正确编写静态 key 与依赖宿主状态的响应式 key。1. Accessor 的定义T | (() T)Accessor是 packages/lit-query/src/accessor.ts 中定义的类型别名type AccessorT T | () T;它的语义在源码注释中已经写得很明确accessor.ts#L1-L12A value that can be passed directly or read from a zero-argument getter. Lit Query APIs read function accessors during host updates, so the getter can depend on reactive host state.也就是说AccessorT接受两种形式静态值直接传T本身例如[todos]这样的查询 key 或完整选项对象零参 getter传一个() T函数getter 在宿主Lit 元素更新时被重新求值因此它可以闭包引用this.userId等响应式宿主状态。类型参数只有一个T表示最终被读出来的值的类型。文档给出的最小示例docs/framework/lit/reference/type-aliases/Accessor.mdconst staticKey: Accessorreadonly unknown[] [todos] const reactiveKey: Accessorreadonly unknown[] () [todos, this.userId]两者类型完全兼容——这正是该类型别名存在的全部意义让同一份 API 签名同时接纳常量配置与随宿主状态变化的配置而不需要拆成两个函数。2. 读取机制readAccessorAccessor只是类型约定真正的求值逻辑由同文件中的readAccessor函数完成accessor.ts#L15-L17export function readAccessorT(value: AccessorT): T { return typeof value function ? (value as () T)() : value }逻辑极其简洁若传入的是函数则调用它取返回值否则原样返回。整个 lit-query 包中凡是把Accessor解析为真实值的地方都走这一个函数。从源码结构看全部调用点分布在各个控制器与状态钩子中调用点解析的对象createQueryController.ts#L302readAccessor(this.options)再交给client.defaultQueryOptions(...)createMutationController.ts#L294readAccessor(this.options)再交给client.defaultMutationOptions(...)createInfiniteQueryController.ts#L342无限查询选项createQueriesController.ts#L296-L297双层解析readAccessor(optionsAccessor)后再readAccessor(resolvedOptions.queries)useIsFetching.ts#L112、useIsMutating.ts#L112过滤器条件readAccessor(this.filters)其中createQueriesController特别值得注意它把queries数组本身也定义成了Accessor因此在 types.ts#L74-L77 中QueriesControllerOptions.queries的类型是AccessorArray...——即查询列表也可以随宿主状态整体变化。3. 求值时机静态选项与函数选项的两条路径Accessor不是简单的延迟取值它在控制器内部对应两条明显不同的初始化路径。以 createQueryController.ts 为例构造函数中createQueryController.ts#L109-L133constructor(host, options, queryClient?) { const initialClient queryClient super(host, createPendingQueryResult(), queryClient) this.options options if (!initialClient) { return } if (typeof options function) { return // 函数 accessor此刻不创建 observer } const defaulted this.defaultOptions(initialClient) const observer new QueryObserver(initialClient, defaulted) ... }可以推断出两条路径的行为差异静态选项构造时立即readAccessor求值、创建QueryObserver并计算乐观结果挂载后马上订阅函数选项构造时直接返回把求值推迟到宿主更新阶段——QueryController.onHostUpdate()createQueryController.ts#L153-L159protected onHostUpdate(): void { if (typeof this.options ! function) { return // 静态选项无需在每次更新时重读 } this.refreshOptions() }refreshOptions最终通过defaultOptions里的readAccessor(this.options)createQueryController.ts#L302重新执行 getter得到与当前宿主状态一致的新选项再通过observer.setOptions(options)应用到观测器上。onHostUpdate的触发源头是 Lit 的 ReactiveController 生命周期BaseController.hostUpdate() 在每次宿主更新时回调它而结果变化后setResult→queueUpdateBaseController.ts#L159-L171会用queueMicrotask触发host.requestUpdate()从而完成getter 读宿主状态 → 选项变化 → observer 更新 → 结果变化 → 宿主重渲染的响应式闭环。createMutationController、createInfiniteQueryController等采用完全相同的模式如 createMutationController.ts#L173-L179。这正是文档中那句 Lit Query APIs read function accessors during host updates 的具体含义getter 的求值不是任意的而是绑定在 Lit 的hostUpdate回调上天然与响应式状态同步且不会在非渲染时机重复求值。4. 在控制器 API 中的实际形态Accessor是 lit-query 对外 API 签名的通用包裹。types.ts 中导出的选项类型全部是Accessor 包裹的选项// QueryControllerOptions AccessorCreateQueryOptions... export type QueryControllerOptions... Accessor CreateQueryOptionsTQueryFnData, TError, TData, TQueryData, TQueryKey // InfiniteQueryControllerOptions、MutationControllerOptions 同理 export type MutationControllerOptions... Accessor CreateMutationOptionsTData, TError, TVariables, TOnMutateResult 因此所有create*Controller工厂函数的第二个参数都是Accessor...类型。index.ts#L5 已将Accessor与ValueAccessor一起从包入口导出供组件作者自行标注 props 或内部工具类型。一个依赖宿主状态的完整用法示意userId为响应式 state 属性getter 每次宿主更新时重读import { LitElement, html } from lit import { createQueryController } from tanstack/lit-query class UserTodosView extends LitElement { private userId 1 private readonly todos createQueryController(this, () ({ queryKey: [todos, this.userId], queryFn: () fetch(/api/users/${this.userId}/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((t) htmlli${t.title}/li)}/ul } }注意当userId变化、宿主重新渲染时onHostUpdate会用新选项重建 observer 的 options查询随之切换。若选项与宿主状态无关直接传静态对象如仓库示例 examples/lit/basic/src/main.ts#L54-L60 中的{ queryKey: [todos], queryFn: fetchTodosFromServer }即可构造期即完成初始化省去更新期的重读开销。5. 兄弟类型ValueAccessor与createValueAccessor读Accessor时应一并了解同文件定义的另一个类型ValueAccessorTaccessor.ts#L32-L43两者方向相反、配合使用export type ValueAccessorT (() T) { readonly current: T } export function createValueAccessorT(getter: () T): ValueAccessorT { const accessor (() getter()) as ValueAccessorT Object.defineProperty(accessor, current, { get: getter, enumerable: true, }) return accessor }输入方向AccessorT——API 接受值或 getter输出方向ValueAccessorT——控制器返回可调用 带current属性的对象createValueAccessor通过Object.defineProperty让current成为一个实时 getter。createQueryController的返回值QueryResultAccessor就是ValueAccessorQueryObserverResult { refetch, suspense, destroy }createQueryController.ts#L42-L51所以渲染代码中this.todos()与this.todos.current等价。源码注释中的示例accessor.ts#L26-L30const query this.todos() const sameQuery this.todos.current这样Accessor系列类型在 lit-query 中构成了一个完整的对称设计宿主状态经Accessor流入控制器控制器结果经ValueAccessor流出到渲染代码。6. 使用建议与小结结合源码行为使用Accessor时可以遵循几条经验与宿主状态无关的选项传静态对象。静态选项在构造期即完成 observer 初始化createQueryController.ts#L128-L132且跳过每次hostUpdate中的重读分支依赖 props/state 的选项传 getter。getter 会在宿主更新时被readAccessor求值闭包捕获的this.xxx总是最新值无需手动重建控制器getter 应保持零参且轻量。它可能随宿主更新频繁执行应避免在其中发起请求或产生副作用求值结果会直接交给defaultQueryOptions/defaultMutationOptions参与 observer 合并queries列表、filters过滤器同样支持Accessor例如useIsFetching(this, () ({ queryKey: [todos, this.userId] }))。AccessorT看起来只是一行联合类型但它是 Lit Query 将 Lit 响应式生命周期与 TanStack Query 观察者模型对接的关键抽象一行T | (() T)配合readAccessor与hostUpdate钩子让声明式配置与响应式配置在同一组 API 签名下无缝共存。【免费下载链接】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),仅供参考
延伸阅读

更多相关文章

2026/9/8 21:19:58

Unity 3D扫描线动态着色实现原理与工程实践

1. 项目概述:为什么“动态着色”的3D扫描线在Unity里不是炫技,而是刚需? “动态着色”这个词在Unity社区里常被当成美术效果的修饰语,但落到“3D扫描线”这个具体任务上,它立刻从视觉糖霜变成工程硬需求。我第一次接到…

2026/9/8 21:19:58

transformers.js 源码解析:前端 Transformer 推理与 ONNX Runtime 实践

先说一下我为什么会对这个项目起劲。以前要在浏览器里跑一个 BERT,大家第一反应都是 TensorFlow.js,但真到用的时候就发现坑很多:模型转换要自己处理、tokenizer 的对齐方式经常对不上、动态 shape 一调就是半天。后来 Hugging Face 做了 tra…

2026/9/9 1:00:55

unibest + uview-plus 下 tabBar 图标不显示?完整排查与解决方案

unibest uview-plus 这套组合最近在 uni-app 社区里讨论热度很高,尤其从老项目往 Vue3 Vite 迁移的同学,基本都会遇到一个问题:pages.json 里 tabBar 配置得好好的,四个导航项的文字都出来了,但底部图标就是不展示。…

2026/9/9 1:00:55

HAWC2_Matlab_tools实战:风电载荷仿真数据从预处理到疲劳分析

简介:这套MATLAB工具集面向风电领域工程师与研究人员,针对丹麦DTU风能公司开发的空气弹性仿真规范HAWC2,提供模型预处理和结果后处理的整套脚本方案,可覆盖湍流风场文件读取、二进制转换、HDF5结果解析、雨流计数与疲劳统计等高频…

2026/9/9 1:00:55

微信小程序咖啡点单系统开发实战:支付对接与蓝牙打印

简介:这是一份用于学习微信小程序开发的完整星巴克咖啡门店界面源码,适合小程序初学者以及想提升移动端界面布局与交互设计能力的开发者。项目中通过WXML与WXSS构建了商品展示、购物车、订单处理、历史记录、个人中心等典型页面,并演示了内置…

2026/9/9 0:55:54

NVIDIA收购Hugging Face后,开发者部署、驱动与容器的技术变局

NVIDIA 以 129.3 亿美元收购 Hugging Face,这个数字刚出来的时候,我朋友圈里做 AI 的朋友基本分成了两派。一派觉得太贵了,一个模型托管平台凭什么值这么多钱;另一派觉得买便宜了,因为 Hugging Face 早就不是“AI 圈的…

2026/9/8 7:15:10

超人会飞不算本事:系统稳定依赖清晰规则与边界设计

开头先不绕弯子。“#斯坦李吐槽dc 所以超人是无缘无故会飞的嘛哈哈哈哈哈哈哈锤哥真是技术人才啊!#雷神 #复联”这类调侃式短标题,第一波冲击力在于它把两个宇宙的角色塞进同一个吐槽箱里,但细想一下就能发现,它真正碰到的根本不是…

2026/9/8 7:15:15

超人VS蜘蛛侠:拆解超级IP的影响力与传播方法论

把“蜘蛛侠 vs 超人”放在 CSDN 上聊,可能很多人第一反应是走错片场了。但如果把这两个角色看成“两个持续运营了 80 多年的文化产品”,你会发现,这场比较本质上是两个不同 IP 策略的长期结果对比:超人赢在定义了整个超级英雄题材…

2026/9/8 7:15:10

基于CNN的调制信号识别:MATLAB实现时频图分类实战

简介:本资源是一套面向通信工程与信号处理方向学习者、研究者的深度学习实践方案,聚焦调制信号自动检测与识别这一典型无线通信任务,解决传统方法依赖人工特征、低信噪比下性能下降等痛点。压缩包共12个文件(10.73MB)&…

2026/9/9 0:00:48

MHS模型硬件标准:让大模型像调用软件一样控制物理设备

让Claude真正看着显微镜说“这个细胞形态不太对”,或者让大模型自己调一版机械臂的运动轨迹,这事儿听上去已经很接近科幻片了。但你真上手试一次就会发现,模型不缺智商,缺的是一个能插进显微镜、机械臂、激光控制器里的“通用插座…

2026/9/9 0:00:48

AI五大核心方向详解:从机器学习到大模型,零基础转行选哪条?

会有人告诉我,他想转行学AI,但打开招聘网站一看直接傻眼:机器学习、深度学习、自然语言处理、计算机视觉、大模型应用……满屏都是这些词,好像每个都会一点,又好像每个都离自己很远。还有人上来就问“学Python还是学Ja…

2026/9/9 0:00:49

从50行最小循环到生产级AI引擎:工程化改造全解析

直接说干货。这一章我写的不是那种"hello world跑通某个模型"的教程,而是把AI引擎当做一个真正要上线、要被人调用、要扛流量的系统来聊。从最初只有50行的最小循环,到能够承载生产流量的AI引擎,中间差的不是代码量,而是…

2026/9/7 16:23:03

USB Type-C PCB布局分区设计:电源、高速信号与PD协议全攻略

做硬件这行,Type-C接口算是典型的“看着简单,做起来全坑”的东西。光引脚就24个,高低速信号、电源、控制线全部塞在一个小小的连接器里,如果PCB布局不做规划,打样回来基本就是“插上没反应”、“高速掉线”、“静电一打…

2026/9/7 22:46:00

系统编程学习原型如何补齐稳定性边界

系统编程学习原型如何补齐稳定性边界预算有限时&#xff0c;我先优化明显多余的复制&#xff0c;而不是猜测性地换容器。用借用传递只读数据通常就能减少分配&#xff1a; fn parse(line: &str) -> Result<Item, Error> { /* ... */ }用基准确认热点确实在分配&am…

2026/9/7 22:45:59

雨花区哪家财务公司代理记账比较好?

在雨花区&#xff0c;企业处理财税事务常常面临诸多挑战&#xff0c;选择一家靠谱的财务公司至关重要。湖南巨勤财务管理咨询有限公司就是本地正规实体财税服务机构&#xff0c;深耕本地工商财税行业多年&#xff0c;熟悉当地工商局、税务局最新政策与申报流程。主营公司注册、…

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
咨询二维码