关键在于用touched和valid两个布尔值建模四态:初始态(false,true)、错误态(true,false)、有效态(true,true)、条件空态(false,false),通过事件驱动状态变更,解耦规则、触发与反馈。

在复杂表单联动中,管理多字段校验状态的关键不是逐个判断字段值,而是把校验过程建模为可预测、可响应的状态流。核心是解耦“规则”“触发”和“反馈”,避免手动调用 validate() 或硬编码 if-else 判断。
用 touched + valid 两个布尔值定义四态
每个字段维护两个独立的布尔状态:touched(是否被用户操作过)和 valid(当前值是否通过所有规则)。组合起来形成四种明确语义的状态:
- touched = false, valid = true:初始态,字段空且未聚焦,不显示错误提示
- touched = true, valid = false:已编辑但校验失败,显示对应错误信息
- touched = true, valid = true:已编辑且全部通过,可提交或进入下一步
- touched = false, valid = false:条件性必空字段(如“非企业用户时税号必须为空”),UI 可据此隐藏或禁用该字段
状态变更靠事件驱动,不靠条件判断
不要在 input 事件里写 if (value.length 。改为定义清晰事件,让状态响应它:
- 用户聚焦输入框 → 触发 TOUCH 事件 → 设置
touched = true - 输入后防抖结束 → 触发 VALIDATE 事件 → 执行该字段全部规则,更新
valid - 关联字段变化(如切换“是否为企业”)→ 触发 RULES_UPDATED → 重新校验当前字段及依赖字段
- 点击提交 → 触发 SUBMIT_ATTEMPT → 强制所有
touched = false字段设为touched = true,再批量校验
跨字段联动通过状态广播实现
字段之间不直接调用方法,而是基于字段路径(如 "user.password")广播和监听事件:
- 密码字段校验通过后,广播 PASSWORD_VALIDATED
- 确认密码字段监听该事件,比对自身值是否一致 → 更新自己的
valid和errorMessage - 密码被清空时,广播 PASSWORD_CLEARED → 确认密码字段自动设
valid = false并清空提示
UI 层只读状态,不查规则
模板中不写逻辑判断,只做状态映射:
- 错误提示显示逻辑:
touched && !valid ? errorMessage : null - 提交按钮禁用逻辑:
form.fields.some(f => f.touched && !f.valid) || form.submitting - 联动显隐逻辑:
showIf: { key: "user.isCompany", value: true }→ 监听user.isCompany的状态变更,自动同步显隐











