ARTICLE DETAIL

资讯详情

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

TanStack Form Vue 的 useFormGroup:组合式 API 下的子表单(Form Group)状态管理

TanStack Form Vue 的 useFormGroup:组合式 API 下的子表单(Form Group)状态管理 TanStack Form Vue 的 useFormGroup组合式 API 下的子表单Form Group状态管理【免费下载链接】form Headless, performant, and type-safe form state management for TS/JS, React, Vue, Angular, Solid, and Lit.项目地址: https://gitcode.com/GitHub_Trending/form/formuseFormGroup是 TanStack Form Vue 适配层提供的组合式函数用于在顶层表单内部创建子表单Form Group从而将多步骤multi-step表单按步骤拆分为独立的表单作用域各自拥有独立的校验、提交与状态元信息同时数据仍然挂在同一个父级值树上。读完本文你将掌握useFormGroup的完整签名、返回值语义api与state、FormGroupApiOptions各配置项的作用并能在 Vue 3 的script setup中组合出多步骤表单、分组校验与分组提交等实战方案。函数签名与定位useFormGroup定义于 packages/vue-form/src/useFormGroup.tsx:221并通过 packages/vue-form/src/index.ts 从tanstack/vue-form导出。其类型签名如下function useFormGroupTParentData, TName, TData, TOnMount, TOnChange, TOnChangeAsync, TOnBlur, TOnBlurAsync, TOnSubmit, TOnSubmitAsync, TOnDynamic, TOnDynamicAsync, TSubmitMeta, TFormOnMount, TFormOnChange, TFormOnChangeAsync, TFormOnBlur, TFormOnBlurAsync, TFormOnSubmit, TFormOnSubmitAsync, TFormOnDynamic, TFormOnDynamicAsync, TFormOnServer, TParentSubmitMeta(opts): object;与useField、useForm一样它是 form-core 中无框架的FormGroupApi类在 Vue 侧的响应式桥接层。函数接收一组选项opts类型为FormGroupApiOptions内部实例化FormGroupApi并通过tanstack/vue-store的useSelector订阅其 store最终返回{ api, state }。类型参数分组签名中 21 个类型参数可归为两组组级Group 级回调类型TOnMount、TOnChange、TOnChangeAsync、TOnBlur、TOnBlurAsync、TOnSubmit、TOnSubmitAsync、TOnDynamic、TOnDynamicAsync它们约束为FormGroupValidateOrFnTParentData, TName, TData异步版本为FormGroupAsyncValidateOrFn即作用于该子表单自身的校验函数表单级父级回调类型TFormOnMount、TFormOnChange、TFormOnChangeAsync、TFormOnBlur、TFormOnBlurAsync、TFormOnSubmit、TFormOnSubmitAsync、TFormOnDynamic、TFormOnDynamicAsync、TFormOnServer它们约束为FormValidateOrFnTParentData/FormAsyncValidateOrFnTParentData用于向FormGroupApi传递父表单的校验逻辑例如TFormOnServer对应服务端校验。这些泛型约束保证了类型安全TName必须是父数据的深键DeepKeysTParentDataTData必须是对应深值DeepValueTParentData, TName。返回值解析api 与 stateuseFormGroup返回一个只读对象包含两个属性api完整的 FormGroupApireadonly api: FormGroupApi... formGroupApi;api是FormGroupApi实例提供类表单的全部命令式方法包括字段操作deleteField、insertFieldValue等、校验、状态更新与提交handleSubmit。在模板中通过v-slot解构出的group就是它。state响应式的分组状态readonly state: ReadonlyRefFormGroupStoreState... groupState;state是一个 Vue 只读Ref指向FormGroupStoreState。由于它由useSelector(formGroupApi.store, (state) state)派生见 packages/vue-form/src/useFormGroup.tsx:296当分组内的值或元数据变化时会自动触发组件重渲染。模板中解构出的state即groupState.value。在模板中使用的两种方式useFormGroup面向script setup组合式用法但更常见的实战方式是通过useForm返回的form.FormGroup组件其内部正是调用useFormGroup见 packages/vue-form/src/useFormGroup.tsx:450-532script setup langts import { useForm } from tanstack/vue-form const form useForm({ defaultValues: { step1: { name: }, step2: { age: 0 }, }, }) /script template form.FormGroup namestep1 v-slot{ group: formGroup } !-- formGroup 拥有 deleteField、insertFieldValue 等类表单方法 -- /form.FormGroup /templateFormGroup组件的默认插槽接收{ group, state }两个作用域插槽属性其中state的类型为FormGroupApi[state]见 packages/vue-form/src/useFormGroup.tsx:133-186。实战多步骤向导表单子表单最常见的应用场景是分步向导每一步一个FormGroup通过外部ref状态条件渲染逐步提交。下面这个例子完整展示了组内提交推进步骤、最后一步提交整个表单的经典模式思路来自 form-groups 指南script setup langts import { ref } from vue import { useForm } from tanstack/vue-form const step ref(0) const form useForm({ defaultValues: { step1: { name: }, step2: { age: 0 }, }, }) const onGroupSubmit () { step.value } const onGroupSubmitInvalid () { // 处理子表单校验失败的情况和顶层表单一样 } /script template form.FormGroup v-ifstep 0 namestep1 :onGroupSubmitonGroupSubmit :onGroupSubmitInvalidonGroupSubmitInvalid :onSubmitMeta{} as SomeType v-slot{ group: formGroup } form submit.prevent.stopformGroup.handleSubmit() !-- formGroup.handleSubmit() 只提交子表单不会触发父表单 onSubmit -- /form /form.FormGroup form.FormGroup v-ifstep 1 namestep2 :onGroupSubmit() form.handleSubmit() v-slot{ group: formGroup } form submit.prevent.stopformGroup.handleSubmit() !-- 最后一步调用 form.handleSubmit() 提交整个表单 -- /form /form.FormGroup /template关键行为由测试 packages/vue-form/tests/useFormGroup.test.tsx 明确验证提交子表单时只调用onGroupSubmit不会触发父表单onSubmit第 11-59 行的should call onGroupSubmit but not the form onSubmit分组值随字段输入响应式更新should expose group state value reactively组级校验失败时调用onGroupSubmitInvalid而不是onGroupSubmit第 105-169 行提交分组时忽略分组作用域之外的表单级字段错误第 171-229 行这正是分组隔离的价值所在onSubmitMeta会随handleSubmit(meta)传递到onGroupSubmit的props.meta第 231-271 行。选项解析FormGroupApiOptionsopts的类型为FormGroupApiOptions...它继承自 FormGroupOptions 接口。核心字段如下选项类型说明nameTNameDeepKeysTParentData必填。分组在父数据树中的路径键如step1validatorsFormGroupValidators分组自身的校验器集合onMount/onChange/onBlur/onSubmit/onDynamic及其 Async 版本onGroupSubmit(props) any \| Promiseany分组校验通过并提交时调用props 含value、meta、groupApionGroupSubmitInvalid(props) void用户提交无效分组时的回调onSubmitMetaTSubmitMeta从handleSubmit传递到提交回调props的附加数据validationLogicValidationLogicFn组自身校验逻辑策略如revalidateLogic()省略时使用父表单的validationLogic或默认值listenersFormGroupListeners挂载到对应事件上的监听器canSubmitWhenInvalidboolean为true时允许在无效状态下提交canSubmit不受校验错误影响默认undefinedasyncAlwaysboolean为true时即使同步校验已有错误也始终执行异步校验asyncDebounceMsnumber异步校验默认防抖毫秒数defaultValueNoInferTData分组的默认值defaultMetaPartialFieldLikeMeta分组的默认元信息defaultStateFormGroupState分组的默认状态disableErrorFlatboolean禁用errors上的flat(1)操作多数场景不建议开启此外opts中还包含父表单级回调onFormMount、onFormChange等见FormGroupApiOptions的TForm*泛型它们会把父表单的校验与生命周期逻辑透传给FormGroupApi保证组与父表单在onDynamic、服务端校验等机制上行为一致。子表单的三种校验能力Form Group 拥有独立的校验流程支持三个层次1. 组级校验template form.FormGroup namestep1 :validators{ onChange: () Error } v-slot{ group: formGroup } !-- formGroup.state.meta.errorMap // { onChange: Error | undefined } -- !-- formGroup.state.meta.errors // (Error)[] -- /form.FormGroup /template2. 同时给子字段设置错误校验函数返回{ group, fields }结构其中fields的键必须是相对于该分组的字段名而不是完整路径template form.FormGroup namestep1 :validators{ onChange: ({ value, groupApi }) ({ group: value.name error ? Group error : undefined, fields: { // 键必须是相对于 FormGroup 的字段名与标准 schema 在分组上的工作方式保持一致 name: value.name error ? Field error : undefined, }, }), } / /template3. 标准 schema 校验分组校验器直接接受 Zod 等标准 schema 对象template form.FormGroup namestep1 :validators{ onChange: z.object({ name: z.string().min(2), }), } / /template之所以使用相对字段名是为了让分组 schema 可组合你可以把step1Schema传给step1分组、把schema包含step1Schema与step2Schema传给父表单这样即使分组被跳过部分校验后的数据依然会在父表单层暴露错误。动态校验的注意事项如果要在分组上使用动态校验onDynamic不要依赖useForm传入的onDynamic——它在子表单提交时不会触发onChange语义详见 动态验证指南。正确做法是把子 schema 传给分组自身的onDynamictemplate form.FormGroup namestep1 :validators{ onDynamic: step1Schema } / /template此时分组会以formGroup.submissionAttempts作为切换提交前后校验器的依据。分组状态元信息通过formGroup.state可以访问分组的值与元信息。formGroup.state.meta中值得关注的属性属性说明isFieldsValid字段级校验器无错误时为trueisGroupValid组级校验器无错误时为trueisValid字段级与组级校验均无错误时为trueisSubmitting分组正在提交过程中为trueisSubmitting常被用于禁用提交按钮与展示加载态。测试 packages/vue-form/tests/useFormGroup.test.tsx:273-328 验证了异步提交期间按钮会从Continue切换为Saving...并禁用提交完成后恢复证实了state的响应式重渲染能力。源码级原理生命周期与选项同步useFormGroup的实现packages/vue-form/src/useFormGroup.tsx:288-316清晰地揭示了它与 Vue 响应式体系的集成方式const formGroupApi (() { const api new FormGroupApi({ ...opts }) return api })() const groupState useSelector(formGroupApi.store, (state) state) let cleanup!: () void onMounted(() { cleanup formGroupApi.mount() }) onUnmounted(() { cleanup() }) watch( () opts, () { // 渲染期间保持选项最新 formGroupApi.update({ ...opts } as never) }, ) return { api: formGroupApi, state: groupState } as const三个关键点实例化FormGroupApi在form-core中完成状态初始化与校验逻辑装配Vue 侧不做任何框架耦合的状态复制挂载/卸载onMounted时调用api.mount()并保存返回的清理函数onUnmounted时执行清理确保监听器与 store 订阅在组件销毁后不泄漏选项热更新通过watch(() opts, ...)在选项对象变化时调用api.update()保证渲染期间传入的校验器、监听器等配置始终与最新渲染保持一致。由于FormGroup组件在 packages/vue-form/src/useFormGroup.tsx:523-529 中直接复用useFormGroup并把group/state注入默认插槽因此组合式 API 与模板组件两条使用路径共享同一套实现与响应式语义。总结useFormGroup是 TanStack Form Vue 中把无框架的FormGroupApi桥接为 Vue 组合式 API 的入口它返回的命令式api提供完整的子表单控制能力state则借助useSelector提供粒度化的响应式分组状态。无论是通过form.FormGroup组件做多步骤向导还是直接调用useFormGroup构建可组合的复杂表单你都能获得类型安全的分组校验、独立的提交回调onGroupSubmit/onGroupSubmitInvalid、提交元信息透传以及与父表单严格隔离的错误作用域。更进一步可以阅读 form-groups 指南 查看完整的分步表单示例或深入 FormGroupApi 类 与 FormGroupOptions 接口 探索全部可用 API。【免费下载链接】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),仅供参考
返回列表