Skip to content
目录

联动系统:Effects / Reactions / x-reactions

1. 两类联动范式

Formily 2.x 同时支持:

  • 主动联动:基于事件(onFieldValueChange 等)显式改状态。
  • 被动联动:基于依赖(reaction/autorun)自动收敛。

在官方高级指南里,这两套都被完整展示(docs/guide/advanced/linkages.zh-CN.md)。


2. 主动联动(事件驱动)

2.1 机制

  • 通过 onForm* / onField* hooks 监听生命周期事件。
  • 在回调中调用 setFieldState/setFormState

2.2 适用场景

  • 一对多控制(单字段影响多个字段);
  • 业务流程节点清晰、可读性优先。

2.3 风险

  • 多对一/循环依赖场景下代码易膨胀;
  • 需要手动组织依赖关系。

3. 被动联动(依赖驱动)

3.1 机制

  • createReactions 内部把 reaction 函数接入 autorun
  • 函数内部读取到的 observable 字段会自动收集依赖;
  • 依赖变更后自动重跑。

3.2 适用场景

  • 计算型联动(价格、汇总、跨字段公式);
  • 多依赖输入到单输出的场景。

3.3 风险

  • 依赖隐式化,排查触发链路时需要响应式思维;
  • 不当写法可能造成循环更新,需要 guard。

4. x-reactions 的运行时本质

@formily/json-schema 中:

  • transformFieldProps 会把 schema 转为 field props;
  • getUserReactions 解析 x-reactions
  • setSchemaFieldState 执行 fulfill/otherwise/target/run
  • dependencies 通过 field.query(...).getIn(...) 提取值。

也就是说,x-reactions 不是“特殊语法糖”,而是 schema 到 core reaction 的编译结果。


5. 为什么联动支持字符串表达式

Formily 提供 {{...}} 表达式编译(compiler.ts),让 Schema 可以序列化携带动态逻辑。
这非常适合后端驱动与低代码平台,但也带来安全边界(详见第 6 章与第 9 章 CSP 讨论)。


6. 延伸追问:字段未挂载时怎么联动?

setFieldState 命中不到字段时,会进入更新订阅队列(subscribeUpdate)。
字段初始化 (initFieldUpdate) 后再回放更新,保证“声明先于渲染”也能成立。

这是动态 Schema 场景下非常实用的可靠性设计。


7. 结合 Issue/PR 的演进信号

联动系统相关的近期演进重点:

  • 链式响应正确性:#4328
  • 降低不必要响应:#4324
  • 数组状态迁移稳定性:#4323#4325

说明 Formily 团队持续在“联动表达力”与“运行时可控性”之间做平衡。

MIT License.