关于 tanstack-vue-form-skilld
面向 Vue 3 的类型安全表单状态库,提供字段、表单组和响应式状态选择能力。适合构建带验证及数组字段的表单。
主要功能
- 01类型安全的表单状态
- 02字段与表单组
- 03同步及异步验证
- 04响应式状态选择
- 05数组字段操作
适用场景
- 01构建 Vue 3 表单
- 02验证字段及表单数据
- 03管理动态数组字段
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ skilld-dev/ vue-ecosystem-skills --skill tanstack-vue-form-skilld安装后在 Claude Code 中输入/tanstack-vue-form-skilld确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
references/api-surface.mdarray-fields.mdform-groups.mdreactivity.mdvalidation.md详细介绍
@tanstack/vue-form 1.33.5
为 Vue 3 提供无头、类型安全的表单状态管理。此包重新导出 @tanstack/form-core 的全部内容,并添加 Vue 组件和钩子(src/index.ts:1-5)。
环境
- 研究版本:
@tanstack/[email protected],打包了@tanstack/[email protected]和@tanstack/vue-store@^0.11.0(package.json:39-42)。 - 对等依赖:
vue ^3.4.0(package.json:48-50)。测试矩阵涵盖 TypeScript 5.4 至 5.9(package.json:54-60)。 - 仅从包根目录导入。唯一的子路径导出是
./package.json(package.json:21-33)。同时支持 ESM/CJS,sideEffects: false。 - 官方文档:https://tanstack.com/form/latest/docs/framework/vue/overview
最简表单
<script setup lang="ts">
import { useForm } from '@tanstack/vue-form'
const form = useForm({
defaultValues: {
fullName: '',
},
onSubmit: async ({ value }) => {
console.log(value)
},
})
</script>
<template>
<form @submit.prevent.stop="form.handleSubmit">
<form.Field name="fullName">
<template v-slot="{ field }">
<input
:name="field.name"
:value="field.state.value"
@blur="field.handleBlur"
@input="(e) => field.handleChange((e.target as HTMLInputElement).value)"
/>
</template>
</form.Field>
<button type="submit">Submit</button>
</form>
</template>
来源:官方快速入门,https://tanstack.com/form/latest/docs/framework/vue/quick-start
字段绑定规则
- 使用
form.Field组件创建字段。name属性必须是defaultValues的深层键,例如'details.email'或`people[${i}].name`。 - 作用域插槽接收
{ field, state }(src/useField.tsx:543-547)。field是一个FieldApi,state与field.state保持一致。 - 输入框采用受控方式:绑定
:value="field.state.value",通过field.handleChange推送更新,并绑定@blur="field.handleBlur"。 - 对于数字输入框,使用
(e.target as HTMLInputElement).valueAsNumber。 - 不要在插槽输入框上使用
v-model;状态通过handleChange流转。 form.Field会在创建字段之前将其属性与透传属性合并(src/useField.tsx:541),因此可通过属性或透传属性传入验证器和监听器。
响应性
- 在
<script setup>中使用form.useSelector((state) => state.values.firstName)。它返回Readonly<Ref<T>>(src/useForm.tsx:155-189)。 form.useStore已弃用;它与useSelector是同一个函数。请优先使用form.useSelector(src/useForm.tsx:190-227, 336-337)。- 在模板中使用
<form.Subscribe>,可选传入selector属性。不设置selector时,插槽会接收整个表单状态(src/useForm.tsx:338-349)。 - 不要直接调用
useField钩子来实现响应性。它专为在form.Field内使用而设计;请改用form.useSelector(官方基本概念说明,https://tanstack.com/form/latest/docs/framework/vue/guides/basic-concepts)。 useSelector和useStore会从@tanstack/vue-store重新导出,用于直接访问原始 store(src/index.ts:2)。
验证要点
- 通过
form.Field上的validators属性或useForm选项中的validators传入验证器。钩子包括:onMount、onChange、onBlur、onSubmit、onDynamic,每种都提供对应的Async版本。 - 验证器在验证通过时返回
undefined,否则返回任意类型的错误(通常是字符串)。错误会保存在field.state.meta.errors和field.state.meta.errorMap中。 - Standard Schema 库可直接用作验证器:Zod v3.24.0 或更高版本、Valibot v1.0.0 或更高版本、ArkType v2.1.20 或更高版本、Yup v1.7.0 或更高版本(官方基本概念指南)。
- 使用
async-debounce-ms属性或每个验证器的onChangeAsyncDebounceMs对异步验证器进行防抖。 - 只有在
useForm选项中设置validationLogic: revalidateLogic()时,onDynamic验证器才会运行。
<form.Field
name="age"
:validators="{
onChange: z.number().gte(13, 'You must be 13 to make an account'),
}"
>
数组字段
- 为外层字段设置
mode="array"。在数组模式下,组件会跟踪state.meta._arrayVersion而不是值,因此子字段编辑不会导致整个列表重新渲染(src/useField.tsx:258-267, src/types.ts:12-15)。 - 使用
v-for遍历field.state.value,并通过深层名称(如`people[${i}].name`)渲染子字段。 - 通过数组方法进行更改:
pushValue、removeValue、swapValues、moveValue、insertValue、replaceValue、clearValues。
表单分组
<form.FormGroup name="step1" v-slot="{ group }">会为表单数据中的一个键构建子表单。插槽接收{ group, state }(src/useFormGroup.tsx:525-529)。group.handleSubmit()只提交并验证该分组;form.handleSubmit()提交整个表单。- 分组验证器可以返回
{ group, fields },其中fields的键相对于该分组;可以按步骤组合 Standard Schemas。
特定版本规则
- 自 v1.28.0 起的重大变更:默认情况下,
field.state.meta.errors会被扁平化,因此是['err'],而不是[['err']]。在字段选项中设置disableErrorFlat: true,即可恢复旧的嵌套格式。发布说明:https://github.com/TanStack/form/releases/tag/%40tanstack%2Fvue-form%401.28.0 - 已弃用:
form.useStore,请改用form.useSelector(src/useForm.tsx:190-192, 336-337)。 - 已弃用:
field.getValue(),请改为读取field.state.value(官方 FieldApi 参考,https://tanstack.com/form/latest/docs/reference/classes/FieldApi)。 Field接受mode: 'value' | 'array'。数组模式用于避免列表重新渲染;参见 https://github.com/TanStack/form/issues/1925(src/useField.tsx:258-259)。useForm会在 Vue 的useId可用时据此生成适用于 SSR 的表单 ID,否则回退到 uuid,以确保服务端标记与客户端水合一致(src/useForm.tsx:272, src/useFormId.ts:18-24)。useFormId本身是内部实现,并未导出(dist/esm/index.js)。- 可复用的选项集:从 form-core 导入
formOptions({ defaultValues }),并展开传入useForm。
注意事项
- Standard Schema 的转换不会保留。
onSubmit始终接收输入数据;如需转换后的输出,请在onSubmit内调用schema.parse(value)(官方提交指南,https://tanstack.com/form/latest/docs/framework/vue/guides/submission-handling)。 - 表单级验证器设置的字段错误可能会被该字段自己的验证器覆盖;在设置表单级字段错误后会运行字段验证(官方验证指南)。
- 同步验证器会先运行;若同步验证失败,则会跳过对应的
Async验证器,除非设置了asyncAlways: true。 - 在表单被触碰之前,
canSubmit为 true。若要在任何交互发生前禁用提交按钮,可组合使用!canSubmit || isPristine。为保证无障碍性,优先使用aria-disabled,而非disabled(官方验证指南)。 Field和FormGroup组件会自动传入父表单。只有单独导出的Field和FormGroup才需要显式设置form选项。- 异步默认值:使用
reactive和computed引用包装(TanStack Query 模式,https://tanstack.com/form/latest/docs/framework/vue/guides/async-initial-values)。
参考资料
- references/api-surface.md:导出项、钩子、组件和核心类方法,附源代码引用。
- references/reactivity.md:选择器、Subscribe、监听器和响应式元数据跟踪。
- references/validation.md:验证器、架构、动态验证、关联字段和提交处理。
- references/array-fields.md:数组字段和数组变更方法。
- references/form-groups.md:子表单、分组验证和分组状态。
评论
支持 Markdown