资讯动态

TanStack Form for Vue:useStore 废弃别名全解与 useSelector 状态订阅机制

发布时间:2026/9/17 15:56:46 来源:尧图企业网站定制
TanStack Form for VueuseStore 废弃别名全解与 useSelector 状态订阅机制【免费下载链接】form Headless, performant, and type-safe form state management for TS/JS, React, Vue, Angular, Solid, and Lit.项目地址: https://gitcode.com/GitHub_Trending/form/form本文围绕tanstack/vue-form的 Vue API 参考页useStore展开讲解这个已废弃变量的完整类型签名、参数结构与返回值语义并结合同仓库源码说明它在useForm返回的表单实例上的真实形态、与useSelector的等价关系以及组件库内部是如何用选择器实现细粒度响应式订阅的。读完后你能准确理解useStore的 API 契约、迁移到useSelector的具体方式并掌握 TanStack Form 在 Vue 中读取表单状态的推荐姿势。useStore 是什么useStore是tanstack/vue-form从底层状态库tanstack/vue-store直接再导出的一个废弃变量deprecated variable。按照 Vue 参考索引 docs/framework/vue/reference/index.md 的列表它被归类在tanstack/vue-form的 Variables 分组中并在条目上带有删除线标记~~useStore~~这是 typedoc 对deprecated标注文档的默认呈现方式。它的全部职责可以用一句话概括useStore是 useSelector 的废弃别名Deprecated alias。原始参考文档 docs/framework/vue/reference/variables/useStore.md 给出的声明为const useStore: TSource, TSelected(source, selector?, compare?) ReadonlyRefTSelected;文档同时标注了它声明的出处node_modules/.pnpm/tanstackvue-store0.11.0_vue3.5.34_typescript5.9.3_/node_modules/tanstack/vue-store/dist/useStore.d.ts:14即它并非vue-form自己实现而是来自tanstack/vue-store这个依赖包的类型声明文件。这一点可以在仓库源码中得到直接印证——packages/vue-form/src/index.ts 中有export { useSelector, useStore } from tanstack/vue-store也就是说tanstack/vue-form只是把useSelector与useStore一并透传给使用方两者指向的是同一个底层能力从一个 store或 atom中选取一段状态切片并把当前组件订阅到该切片上。在依赖版本上packages/vue-form/package.json 声明了tanstack/vue-store: ^0.11.0作为运行时依赖vue为 peer dependency^3.4.0。因此本文描述的行为与类型均基于tanstack/vue-store0.11.x 与 Vue 3.5 这一组合。类型参数与参数签名原始文档完整列出了useStore的类型参数与参数这里逐项继承并展开。类型参数类型参数定义说明TSourceTSource来源 store 的状态类型即source中get()返回的类型TSelectedTSelected NoInferTSource选择器投影出的切片类型默认为整个TSourceNoInfer表示它不从入参位置被隐式推断而是由 selector 的返回值决定使用NoInferTSource作为TSelected的默认值是一个刻意的类型设计当你省略 selector、直接订阅整个状态时切片类型默认退回完整状态类型当传入 selector 时切片类型只由 selector 的返回类型推导避免入参状态类型干扰返回值推断。参数列表source—— 订阅来源其结构包含两个成员get: () TSource同步获取当前状态的快照subscribe: (listener) object注册状态变更监听器返回一个包含取消订阅能力的对象store 句柄。这正是 TanStack Store 的SelectionSource协议任何实现了get/subscribe的对象都可以作为来源包括Store实例和 atom。selector?—— 可选的投影函数签名(snapshot) TSelected。传入后组件只订阅selector返回的切片不传则订阅整个TSource。compare?—— 可选的比较函数签名(a, b) boolean。用于判断两次选择结果是否相等只有判定为变化时才触发更新可用于实现浅比较等定制化的去重策略。返回值ReadonlyRefTSelected返回一个只读的 VueRef其value始终持有 selector 投影出的最新切片。只读意味着你不应、也无法通过该 ref 直接写状态写操作应通过表单/字段 API 提供的方法完成。用法示例原始文档给出的最小示例如下以counterStore为例const count useStore(counterStore, (state) state.count)迁移到useSelector后完全等价且可以显式读取.valueconst count useSelector(counterStore, (state) state.count) console.log(count.value)省略 selector 时则订阅整个值例如直接取 atom 的当前值const value useSelector(countAtom)由于返回的是响应式Ref在模板中可直接解包使用如{{ count }}在脚本中访问.value即可拿到当前切片值。在表单实例上的形态form.useStore 与 form.useSelector除了顶层再导出外useStore在 Vue 中最常见的实际使用位置其实是useForm()返回的表单实例上。从源码 packages/vue-form/src/useForm.tsx 的VueFormApi接口定义看接口上并排声明了两个方法useSelector: TSelected(selector?) ReadonlyRefTSelected推荐useStore: TSelected(selector?) ReadonlyRefTSelected带 JSDoc 标注deprecated Use form.useSelector instead.见 docs/framework/vue/reference/interfaces/VueFormApi.md二者的关键差异在于表单实例上的版本已经预绑定了source你只需要传 selector。其实现见 packages/vue-form/src/useForm.tsxconst subscribeToStore (selector?: (state: never) unknown) useSelector(api.store as never, selector as never) as never extendedApi.useSelector subscribeToStore /** deprecated Use form.useSelector instead. */ extendedApi.useStore subscribeToStore可以清楚看到form.useStore与form.useSelector被赋予了同一个函数引用subscribeToStore内部统一走tanstack/vue-store的useSelector并把来源固定为api.storeFormApi内部的 TanStack Store。省略 selector 时默认返回类型是完整的FormState...通过NoInferFormState...作为TSelected的默认值约束在类型签名中。因此典型的 Vue 表单用法是import { useForm } from tanstack/vue-form const form useForm({ defaultValues: { name: } }) // 推荐写法只订阅需要的切片 const isSubmitting form.useSelector((state) state.isSubmitting) const status form.useSelector((state) state.status)useForm源码注释中还留有一行示意见 packages/vue-form/src/useForm.tsx// formApi.useStore((state) state.isSubmitting)说明官方文档示例中读取提交状态的场景同样适用于 selector 订阅。Subscribe 组件selector 的组件化形态同一个useForm实现还额外挂载了一个Subscribe组件packages/vue-form/src/useForm.tsxextendedApi.Subscribe defineComponent( (props, context) { const allProps { ...props, ...context.attrs } const selector allProps.selector ?? ((state: never) state) const data useSelector(api.store as never, selector as never) return () context.slots.default!(data.value) }, { name: Subscribe, inheritAttrs: false }, )它的语义与form.useSelector一致把selectorprop缺省时为恒等函数即订阅整个FormState作为 props 传入组件内部调用useSelector(api.store, selector)并把选中值data.value交给默认插槽。在模板中即可写Form.Subscribe selector(state) state.isSubmitting template #defaultisSubmitting button :disabledisSubmitting提交/button /template /Form.Subscribe为什么废弃 useStore统一命名与 selector 语义useStore这个名字容易让人误以为拿到的是整个 store而实际上它的第二个参数就是 selector行为与useSelector完全一致。将其标记废弃并统一收敛到useSelector是命名语义上的正名选择而非取 store。这也与tanstack/vue-store自身的文档一致——在 Vue 参考的 useSelector 页中useSelector被描述为 the primary Vue read hook for TanStack StoreVue 端的主要读取 hook返回一个持有选中值的只读 ref省略 selector 即订阅整个值。迁移方式非常简单属于等价替换// 旧废弃 const count useStore(counterStore, (state) state.count) const isSubmitting form.useStore((state) state.isSubmitting) // 新 const count useSelector(counterStore, (state) state.count) const isSubmitting form.useSelector((state) state.isSubmitting)库内部实现selector 订阅如何支撑细粒度渲染理解useSelector的价值最好的参照是vue-form自身对它的深度使用。在 packages/vue-form/src/useField.tsx 中useField为每个需要响应式渲染的元数据分别建立了独立的 selector 订阅const reactiveStateValue useSelector(/* fieldApi.store, (state) state */) const reactiveMetaIsTouched useSelector(/* ..., (state) state.isTouched */) const reactiveMetaIsBlurred useSelector(/* ..., (state) state.isBlurred */) const reactiveMetaIsDirty useSelector(/* ..., (state) state.isDirty */) const reactiveMetaErrorMap useSelector(/* ..., (state) state.errorMap */) const reactiveMetaErrorSourceMap useSelector(/* ..., (state) state.errorSourceMap */) const reactiveMetaIsValidating useSelector(/* ..., (state) state.isValidating */)同理packages/vue-form/src/useFormGroup.tsx 中组级状态也经由useSelector(formGroupApi.store, (state) state)获得响应式读取。从源码结构看这种一个渲染关注点一个 selector的组织方式意味着某字段值变化时只有依赖该切片的 ref 会更新isTouched、isDirty等元数据各自的订阅互不牵连。这正是选择器订阅模型配合可选的compare比较函数去重在 headless 表单场景下控制渲染范围的核心机制也是useStore/useSelector这一 API 在整个tanstack/vue-form体系中的实际地位——它是所有响应式表单状态读取的统一入口。小结useStore是tanstack/vue-form透传自tanstack/vue-store的废弃变量API 参考页为 docs/framework/vue/reference/variables/useStore.md其完整契约为TSource, TSelected(source, selector?, compare?) ReadonlyRefTSelected其中TSelected默认为NoInferTSource它是 useSelector 的等价别名新代码应一律改用useSelector顶层导入或form.useSelector后者已预绑定form.store作为 source在 packages/vue-form/src/useForm.tsx 中form.useStore与form.useSelector共享同一实现subscribeToStoreSubscribe组件是同一机制的模板化封装库内部的useField/useFormGroup均通过大量独立 selector 订阅实现细粒度响应式渲染印证了selector 只读 Ref这一订阅模型的设计意图。【免费下载链接】form Headless, performant, and type-safe form state management for TS/JS, React, Vue, Angular, Solid, and Lit.项目地址: https://gitcode.com/GitHub_Trending/form/form创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

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

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

免费获取报价