Skip to content
目录

高频问答与参考回答

1. Formily 和普通表单库的本质差异是什么?

:Formily 的核心是表单领域模型(@formily/core)+ 响应式运行时(@formily/reactive),而不是一组 UI 组件。它把状态、联动、校验放在模型层,UI 只做渲染映射。


2. 为什么 Formily 在大表单里通常更稳?

:字段级状态拆分 + 精准依赖收集 + batch 调度,避免整树重渲染。动态数组还做了字段状态转置,防止索引变动导致状态错位。


3. addresspath 有什么区别?

  • address:节点绝对路径(保留 VoidField 层级)。
  • path:数据路径(读写 values 的真实路径,通常跳过无数据结构节点)。

4. display: nonehidden 的区别?

  • none:隐藏且剔除提交值(可缓存回写)。
  • hidden:隐藏但保留值。

5. Formily 如何实现“字段未挂载也能 setFieldState”?

:通过更新队列机制(subscribeUpdate),先记录 patch,字段初始化后回放。


6. x-reactions 的底层是什么?

:Schema 层把 x-reactions 编译为字段 reactions 函数,最终通过 core 的 setFieldState / setState 生效。


7. 为什么要同时保留主动联动和被动联动?

:主动联动在一对多场景更直观,被动联动在多依赖计算更简洁。两者适配不同复杂度与可读性需求。


8. Formily 的校验是怎么组织的?

@formily/validator 执行规则,反馈写入字段 feedbacks,并区分 validate 结果与 effect 注入结果(Validate* / Effect*)。


9. 为什么 form.validate(pattern) 还能只校验局部?

:校验内部先 query(pattern),只收集命中字段任务;并受 validatePattern/validateDisplay 进一步过滤。


10. ArrayField 为什么不能只操作数组值?

:只改值会导致字段状态(错误、脏态、组件 props)与索引错位。Formily 会同步迁移字段图状态。


11. Formily 为什么要有 Graph(getFormGraph/setFormGraph)?

:用于全量状态快照导入导出(调试、回放、时光旅行、复杂表单状态持久化)。


12. Formily 表达式编译为什么有争议?

:默认 new Function 能力强但有 CSP 安全边界,严格环境会触发 unsafe-eval。可用 registerCompiler 替换。


13. React 绑定层为什么还能做到性能好?

:React 组件通过 observer 只订阅 render 实际读取字段属性;模型层变更不会自动扩散到整棵组件树。


14. React StrictMode 下如何避免响应器泄漏?

reactive-react 里使用 useCompatFactory + GarbageCollector 做兜底清理。


15. 什么时候选 Formily,什么时候不选?

适合

  • 动态字段多;
  • 联动复杂;
  • 后端驱动 schema;
  • 多团队复用统一建模能力。

不太适合

  • 简单静态表单;
  • 团队无法接受较高抽象成本;
  • 业务只需轻量受控输入。

16. 如果你来设计 Formily,会最关注什么风险?

  • 联动链路可观测性(调试复杂);
  • 表达式编译安全边界;
  • 动态数组状态一致性;
  • 版本升级下协议兼容(polyfill/patch)。

17. 如何回答“Formily 比 react-hook-form 好在哪里”?

答法建议:不做绝对比较,强调定位差异。
Formily 强在领域模型与协议化动态能力;react-hook-form 强在轻量与原生表单范式。选型取决于业务复杂度与团队建模诉求。


18. 一句话总结(终面版)

“Formily 通过响应式领域模型把表单从 UI 状态管理问题升级为可编排的业务建模问题,核心价值在复杂动态场景下的可维护性与可扩展性,而不仅是输入框渲染性能。”


19. 直接用 Formily 时,有没有最佳实践和错误用例对照?

:有,而且非常值得在团队里沉淀成 checklist。下面这份是我结合官方进阶指南(联动/校验/解构)+ Web 检索到的社区高频坑 + GitHub issue 提炼出来的“对照版”。

场景最佳实践(推荐)错误用例(避免)真实依据
动态联动简单一对多用 onFieldValueChange;多依赖计算用 x-reactions.dependenciesonFieldReact所有联动都塞进一个巨型 x-reactions,依赖关系不可读、难排查官方进阶联动指南(仓库 docs/guide/advanced/linkages.zh-CN.md
字段未挂载时更新form.setFieldState,利用内置“延迟回放”机制手写 setTimeout 轮询等字段出现再更新core subscribeUpdate/initFieldUpdate 机制
初始化阶段改值初始化 early phase 优先 form.setValuesIn 或在字段 mount 后改值在字段第一次 reaction(initialized=false)直接 field.setValue 期待必生效#3673
组件 props 联动setComponentProps 传稳定结构,避免把“会变引用的大对象”放入组件 useEffect 依赖useEffect(()=>onChange(), [props.xxx]) + 每次 reaction 生成新引用,导致循环触发#4169
ArrayField 删除/移动ArrayField 自带 push/remove/move 等 API,依赖 onFieldInputValueChange 观察用户输入与结构变化手动改数组值、或错误监听导致多次触发/错位触发#2947, #4130, #4323, #4325
复杂响应链保持 reaction 幂等,必要时拆分 effect;升级时关注 reactive 修复在 reaction 内做大量副作用且无幂等保护,出现链式遗漏或重复触发#4324, #4328
Schema 动态排序字段排序优先结构层控制(schema 顺序 / 渲染层策略)期望通过 x-reactions 动态改 x-index 实时重排#3508
表达式编译安全强 CSP 项目用 registerCompiler 替换默认编译器;明确表达式来源可信默认开启表达式编译并直接吃不可信输入,或忽略 CSP 报错#4338
可编辑容器类组件先确认字段是否真实渲染并参与 reaction,再设计 setFieldState 更新路径认为所有 UI 容器都等价于常规字段渲染节点#3010

可落地的团队规范(建议直接抄到项目 README)

  1. 联动分层:公式型联动走 dependencies,流程型联动走 effects
  2. 数组操作规范:只用 ArrayField API,不直接 splice(values.xxx)
  3. 副作用规范:reaction 函数保持幂等,异步逻辑必须有竞态保护。
  4. 安全规范:生产环境默认评审 表达式来源;CSP 项目强制自定义 compiler。
  5. 排障规范:任何“触发次数异常”先查 display/patterninitializeddependencies、数组索引迁移。

如果继续追问“你在项目里怎么防这些坑”,就回答:用 lint 规则 + code review checklist + 关键联动单测(数组增删/隐藏显示/reset/submit 组合),而不是只靠个人经验。

MIT License.