性能设计与工程化权衡
1. 性能问题的本质
传统受控表单常见问题:
- 表单状态集中在组件树,输入一次触发大范围重渲染;
- 联动越复杂,状态同步越重;
- 动态数组/动态字段导致 diff 与状态迁移成本上升。
Formily 的策略是“模型层拆分 + 精准订阅 + 批量调度”。
2. 四个核心优化抓手
2.1 字段级状态管理
每个字段是独立模型对象,读取/更新按字段颗粒触发,不依赖整树 React state。
2.2 响应式依赖收敛
reaction 只订阅 render/逻辑中实际读取到的属性,避免粗粒度订阅。
2.3 batch/action 边界
批量更新统一 flush,减少中间态触发次数。
2.4 数组状态转置
spliceArrayState/exchangeArrayState 在数组操作时同步迁移字段图状态,防止错位渲染与无效重建。
3. 与可靠性相关的性能折中
3.1 display=none 的“值剔除 + 缓存回写”
优点:
- 提交数据更干净;
- 可避免隐藏字段参与校验与联动污染。
代价:
- 需要缓存恢复机制;
- 边界 case 复杂(社区出现过回写相关修复)。
3.2 提交/校验状态延迟上屏
setValidating/setSubmitting/setLoading 内使用了短延迟阈值,减少瞬时闪烁。
4. 近期社区演进信号(性能/正确性)
- perf(reactive): optimize arrayField performance #4327
- fix(core): avoid arrayField spliceArrayState removing unexcepted fields #4323
- fix(core): fix possible missing spliceArrayState #4325
- fix(reactive): avoid unneccessary reaction #4324
- fix(reactive): avoid chain reactions missing #4328
这些 PR 共同说明:
- Formily 对“性能优化”的前提是语义正确;
- 高频优化点集中在数组场景与 reaction 调度。
5. 工程化落地建议(实践向)
- 大表单优先 schema 分段渲染,不要一次挂载全部深层结构。
- 对复杂
x-reactions做命名 scope 函数封装,降低表达式复杂度。 - 异步联动与异步校验要显式处理 loading 状态与竞态。
- 对核心联动逻辑补单测,优先测“数组增删改 + 隐藏显示 + 重置提交”组合场景。
6. 回答模板
“Formily 的性能不是单点优化,而是系统性设计:
模型层拆分字段状态、响应式精确依赖收集、batch/action 合并调度、数组状态转置保证正确迁移。
它解决的是‘复杂动态表单在规模化场景下的可持续性能’问题。”