Skip to content
目录

@formily/core 表单领域模型

1. 核心对象关系

  • Form:顶层聚合根,持有 values/initialValues/fields/heart/graph
  • Field:基础数据字段,负责 value/validator/feedback/input 生命周期。
  • ArrayField:在 Field 基础上增强数组操作 + 子节点状态转置。
  • ObjectField:增强对象属性增删与子节点清理。
  • VoidField:不参与数据提交,负责结构与 UI 控制。
  • Query:按 path/address 模式查询字段集合。
  • Graph:导入导出全量状态图(time-travel/快照场景)。
  • Heart + LifeCycle:事件总线与生命周期 hook 执行器。

2. Form 的关键设计

2.1 values 与 initialValues 并存

Form 同时维护:

  • values:当前提交值
  • initialValues:重置基线

并通过 observe 深监听触发:

  • ON_FORM_VALUES_CHANGE
  • ON_FORM_INITIAL_VALUES_CHANGE

2.2 “字段值不单独存储”的幂等策略

Field.value 实际读写的是 form.values[path]
这保证“字段状态与提交数据”天然一致,避免双写源引发不一致。

2.3 延迟更新队列(字段尚未出现时)

setFieldState 如果没匹配到字段,会通过 subscribeUpdate 进入更新队列,等字段初始化后应用。
这是动态渲染表单非常关键的“最终一致性”机制。


3. Field 的关键规则

3.1 address 与 path 双路径

  • address:节点绝对路径(包含 VoidField 层级)
  • path:数据路径(跳过不影响数据结构的 Void 层)

这就是为什么同一字段可被两类路径查询命中。

3.2 display 语义不是简单布尔

  • visible:显示,数据存在
  • hidden:隐藏,数据保留
  • none:隐藏,数据从 values 移除(并可缓存回写)

Field.makeReactive 对 display 切换有专门的缓存写回逻辑。

3.3 modified 传播

modifySelf 不只改当前字段,还会向父级数据字段与 form 传播 modified=true,用于“用户是否真实改动过”的语义判断。

3.4 feedback 与 validator 结果隔离

validate 产出的反馈 code 与 effect 人工写入的反馈 code 分离(Validate* vs Effect*),避免污染。


4. ArrayField / ObjectField 的难点

4.1 ArrayField 不只改值,还要改“字段图”

spliceArrayState/exchangeArrayState 会同步迁移或删除子字段节点,保证:

  • 数组值顺序变更;
  • 字段状态(错误、脏态、组件 props)也随索引迁移。

这也是 Formily 做“复杂动态数组表单”比手写方案稳的关键。

4.2 ObjectField 的 additionalProperties 跟踪

addProperty/removeProperty 会维护 additionalProperties 集合,并在 key 变化时清理已失效子节点。


5. 提交、校验、重置的统一编排

batchSubmit / batchValidate / batchReset 统一由 internals 编排:

  • 自动切换 submitting/validating/loading
  • 触发完整生命周期;
  • 在 form/field 两级都可复用同一套行为。

这是典型“领域服务函数”设计,降低对象方法复杂度。


6. 设计评价

优点:

  • 模型边界清晰,复杂行为可组合;
  • 生命周期可扩展,生态 hook 统一;
  • 动态字段与数组场景鲁棒。

成本:

  • 需要理解 path/address/display/pattern 等概念;
  • 错误定位常常需要跨模型层和 UI 层同时排查。

MIT License.