HouseForm 字段联动技巧:listenTo 如何实现密码确认等跨字段校验
【免费下载链接】houseformSimple to use React forms, where your validation and UI code live together in harmony.项目地址: https://gitcode.com/gh_mirrors/ho/houseform
HouseForm 是一款将校验逻辑与 UI 代码"同住一屋"的 React 表单库,而字段联动(跨字段校验)正是它最实用的高级能力之一。本篇文章将围绕 HouseForm 的listenTo属性,手把手教你实现密码确认、条件字段等跨字段校验场景,帮你彻底告别"两个字段各校各的"的尴尬局面。
HouseForm 主打"Simple to use React forms, where your validation and UI code live together in harmony."——校验逻辑直接写在 UI 组件旁边,一个Field组件即可完成取值、渲染、校验。但当表单中两个字段相互依赖时(例如"密码"与"确认密码"),事情就没那么简单了。接下来我们就用listenTo轻松化解。
为什么表单字段需要联动?
大多数表单校验是"各自为政"的:用户名只校验用户名,邮箱只校验邮箱。但真实业务中常有跨字段依赖:
- 密码与确认密码必须一致;
- 选择"公司用户"时才需要填写"公司名称";
- 结束日期不得早于开始日期。
如果不做字段联动,用户先填完"确认密码",再回头修改"密码",表单里仍残留"两次密码不一致"的错误提示——体验很差。这就是HouseForm 跨字段校验要解决的问题。
listenTo 一行代码实现字段监听
HouseForm 的解决方案非常直接:在Field组件上添加listenTo属性,传入一个字段名数组,当被监听的字段触发变更或失焦时,监听方会同步重新执行对应校验。相关类型定义位于 lib/field/types.ts:
<Field name="confirmpassword" listenTo={["password"]} onChangeValidate={(val, form) => { if (val === form.getFieldValue("password")!.value) { return Promise.resolve(true); } else { return Promise.reject("Passwords must match"); } }} > {/* ... */} </Field>其中form.getFieldValue("password")用于在某个字段的校验函数里读取其他字段的值,这正是跨字段校验的数据来源。官方对该用法的完整讲解见 linked-fields.md。
实战:用 listenTo 实现密码确认校验
下面是一个完整的密码确认表单,两步走即可搞定:
第一步,密码字段做基础长度校验;第二步,确认密码字段通过listenTo={["password"]}监听密码字段,并在onChangeValidate中比对两个值:
import { Form, Field } from "houseform"; import { z } from "zod"; const App = () => ( <Form onSubmit={(values) => alert(JSON.stringify(values))}> {({ submit, isValid }) => ( <> <Field name="password" onChangeValidate={z.string().min(8, "至少8个字符")} > {({ value, setValue, onBlur, errors }) => ( <div> <input type="password" placeholder="密码" value={value} onBlur={onBlur} onChange={(e) => setValue(e.target.value)} /> {errors.map((error) => <p key={error}>{error}</p>)} </div> )} </Field> <Field name="confirmpassword" listenTo={["password"]} onChangeValidate={(val, form) => { if (val === form.getFieldValue("password")!.value) { return Promise.resolve(true); } return Promise.reject("两次输入的密码不一致"); }} > {({ value, setValue, onBlur, errors, isTouched }) => ( <div> <input type="password" placeholder="确认密码" value={value} onBlur={onBlur} onChange={(e) => setValue(e.target.value)} /> {isTouched && errors.map((error) => <p key={error}>{error}</p>)} </div> )} </Field> <button disabled={!isValid} onClick={submit}>提交</button> </> )} </Form> );💡 关键点:加了listenTo后,只要用户修改"密码"字段,HouseForm 就会自动重新校验"确认密码"字段,错误提示实时刷新,不再残留过期错误。
listenTo 背后的工作原理
listenTo的实现并不神秘,核心逻辑在 lib/field/use-field-like.ts 的useListenToListenToArray函数中:
- 监听方把自己注册到被监听字段的
onChangeListenerRefs、onBlurListenerRefs、onMountListenerRefs三组回调列表里; - 当被监听字段调用
setValue时,通过setTimeout触发对应回调(见 use-field-like.ts),驱动监听方重新执行校验; - 组件卸载时会自动清理监听器,避免内存泄漏。
简单说:listenTo= "订阅他人事件 + 重跑自己的校验",优雅且零侵入。
更多联动场景:监听多个字段与条件字段
listenTo支持数组,一次监听多个字段,比如日期区间校验:
<Field name="endDate" listenTo={["startDate"]} /* ... */ />另一个常见的字段联动场景是条件显隐:根据一个字段的值决定是否渲染另一个字段。你可以利用Form的value属性实现,例如邮箱为 Gmail 时隐藏密码字段,完整示例同样见 linked-fields.md 的 "Conditional Fields" 章节。
使用 listenTo 的注意事项
listenTo传的是字符串数组,即使只监听一个字段也要写成["password"]形式;- 监听字段触发
onBlur时,监听方会执行自己的onBlurValidate,触发onChange时执行onChangeValidate,两类校验可分开配置; - 想了解
listenTo的完整 API 说明,可查阅 field.md 参考文档,其中对listenTo的语义有精确定义。
总结
HouseForm 的listenTo用一行属性就解决了表单字段联动难题,无论是密码确认这类跨字段校验,还是复杂的条件表单,都不需要引入额外的状态管理或手工触发校验。如果你想在自己的 React 项目中亲自体验,也可以直接git clone https://gitcode.com/gh_mirrors/ho/houseform查看源码与测试用例(如 field.spec.tsx 中的监听场景)。学会它,你的表单体验将立刻上一个台阶!🚀
【免费下载链接】houseformSimple to use React forms, where your validation and UI code live together in harmony.项目地址: https://gitcode.com/gh_mirrors/ho/houseform
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考