Skip to content
目录

JSON Schema 编译与协议扩展

1. Schema 层在 Formily 里的定位

@formily/json-schema 做的不只是“类型描述”,而是:

  • 协议化字段定义(x-component/x-decorator/x-reactions);
  • 表达式编译({{...}});
  • 运行态落地(转换为 IFieldFactoryProps)。

2. Schema 类的关键能力

Schema 类包含:

  • fromJSON/toJSON:协议对象与实例互转;
  • setProperties/setItems/...:构建树;
  • compile/shallowCompile:表达式求值;
  • toFieldProps:转成 core 可消费字段参数。

额外机制:

  • registerPatches:协议补丁;
  • registerPolyfills/enablePolyfills:版本兼容补丁;
  • registerCompiler:替换默认表达式编译器。

3. 表达式编译机制与边界

默认实现使用:

  • new Function('$root', 'with($root){...}')

优点:

  • 实现简单;
  • 表达式能力强;
  • 对 schema 字符串可直接求值。

问题:

  • 严格 CSP 场景会命中 unsafe-eval 限制。

相关 issue:

工程建议:

  • 企业内网/强 CSP 项目优先通过 registerCompiler 替换默认编译器;
  • 文档中明确安全边界,不把表达式编译暴露给不可信输入。

4. x-reactions 如何落到字段状态

核心链路:

  1. 计算 $deps/$self/$form/$values 等上下文。
  2. when 条件编译后选择 fulfill/otherwise
  3. state 写入通过 patchCompile(字段状态)或 patchSchemaCompile(schema 属性映射)完成。
  4. target 字段通过 form.setFieldState(target, ...) 生效。

这里的“schema 状态映射”由 SchemaStateMap 定义,例如:

  • x-component-props -> componentProps
  • x-display -> display
  • enum -> dataSource

5. 为什么 schema compile 里大量使用 untracked

因为 schema 编译过程需要“写状态但不订阅这些写入本身”,否则容易造成依赖污染与无意义重跑。
所以 patchCompile/patchStateFormSchema 都在 untracked 中执行。


6. 关键点:Schema 不是静态配置

很多候选人会把 Formily Schema 说成“纯 JSON 配置”。
准确说法应是:

Formily Schema 是“可执行协议对象”,支持表达式、依赖联动、运行时补丁、版本 polyfill,是具备轻量 DSL 属性的动态配置系统。


7. 关联演进证据

  • React 19 生产环境属性传递兼容修复:#4308
  • 插槽能力增强(Schema 动态渲染表达力):#4259
  • 解构 key 数据回写修复:#4118#4119

MIT License.