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 如何落到字段状态
核心链路:
- 计算
$deps/$self/$form/$values等上下文。 when条件编译后选择fulfill/otherwise。state写入通过patchCompile(字段状态)或patchSchemaCompile(schema 属性映射)完成。- 对
target字段通过form.setFieldState(target, ...)生效。
这里的“schema 状态映射”由 SchemaStateMap 定义,例如:
x-component-props -> componentPropsx-display -> displayenum -> dataSource
5. 为什么 schema compile 里大量使用 untracked
因为 schema 编译过程需要“写状态但不订阅这些写入本身”,否则容易造成依赖污染与无意义重跑。
所以 patchCompile/patchStateFormSchema 都在 untracked 中执行。
6. 关键点:Schema 不是静态配置
很多候选人会把 Formily Schema 说成“纯 JSON 配置”。
准确说法应是:
Formily Schema 是“可执行协议对象”,支持表达式、依赖联动、运行时补丁、版本 polyfill,是具备轻量 DSL 属性的动态配置系统。