架构说明
DynamicForm 4.2 由 @whynotsnow/dynamic-form-core 纯核心包和 @whynotsnow/dynamic-form React/AntD 兼容包组成。core 承载 Field Address、统一节点树、Adapter / Module / Rule / Compiler 预处理能力、配置处理、配置诊断和纯 Runtime resolver;React/AntD 包承载 DynamicForm、Provider、hooks、Form Adapter / Renderer Adapter、component registry、默认 AntD renderer 和 effect handler runtime。核心目标是让字段逻辑标识和值路径分离,并让外部输入归一化、领域模块展开、配置解析、状态维护、运行时策略、表单值读写和 UI 渲染各自保持清晰边界。
仓库结构
当前仓库是 monorepo:
packages/dynamic-form-core/是纯 core npm 发布包边界,包含配置、compiler、adapters、rules、纯 Runtime 和共享纯类型。packages/dynamic-form/是 React/AntD npm 发布包边界,依赖 core 并继续 re-export core 公共 API。packages/dynamic-form/docs/是 React/AntD 兼容入口文档的维护源,随 npm 包一起维护和发布。- 根
docs/只维护 monorepo 级文档,例如 workspace 结构、发布流程、站点规划和仓库维护规则。 apps/docs-site/是 Docusaurus 文档站,使用站点自己的 zh-CN docs 和i18n/en文档内容。demos/保留 Vite demo 和demoRegistry,站点只复用 demo 组件与注册信息,不复制 demo 业务逻辑。
模块关系
4.2 主流程仍然是 FormConfig -> adapter/compiler -> processFormConfig -> Runtime -> renderer。DynamicForm 继续接收现有 FormConfig;Adapter、Compiler、Rule Engine 和 Schema Adapters 是可选预处理层,最终仍输出标准 FormConfig。fields、groups 和 nodes 会在 Config Layer 归一成同一棵节点树。未传 formAdapter / renderer 时,默认使用 createAntdFormAdapter(form) 和 antdRenderer。区别在于 UI-library agnostic 的配置、编译、规则和纯 Runtime 能力已归属 core 包,React/AntD 包负责消费这些能力并提供默认渲染运行时。
关键文件
packages/dynamic-form-core/src/adapters/:把 module-like、JsonSchema、OpenAPI 和 metadata 输入归一化为ModuleFormConfig。packages/dynamic-form-core/src/modules/:定义FieldModule协议和模块注册器。packages/dynamic-form-core/src/rules/:校验、求值声明式规则,并把规则编译为标准 effects。packages/dynamic-form-core/src/compiler/compileFormConfig.ts:把ModuleFormConfig编译为标准FormConfig和组件注册表。packages/dynamic-form-core/src/config/processor/configParser.ts:归一化节点树,生成effectMap、nodeRegistry、containerRegistry、fieldRegistry、initialValues、初始化后的字段和 container 状态。packages/dynamic-form-core/src/runtime/:解析字段、container 和 group 的纯运行时能力,并提供 inspection helpers。packages/dynamic-form/src/CompiledDynamicForm.tsx:把 compiler 产物及其组件注册表接入DynamicForm。packages/dynamic-form/src/index.tsx:拆分DynamicFormProps,把引擎层 props 交给 Provider,把 UI 层 props 交给 FormContent。packages/dynamic-form/src/consumer/provider/DynamicFormProvider.tsx:初始化 store、effect engine 和 React context。packages/dynamic-form/src/consumer/formAdapter.ts:提供默认 AntD form adapter,并把旧form实例转换为中立DynamicFormFormAdapter。packages/dynamic-form/src/state/useStoreInit.ts:处理配置、创建 reducer state、合并初始值并通过 form adapter 同步到表单运行时。packages/dynamic-form/src/state/reducer.ts:用 Immer 处理字段 meta、分组 meta 和动态 UI 配置更新。packages/dynamic-form/src/consumer/render/FormContent.tsx:遍历 Runtime 节点,调用 renderer adapter,并连接提交、变更事件。packages/dynamic-form/src/consumer/render/antdRenderer.tsx:默认 AntD renderer,负责Form、Form.Item、Form.List、Row、Col、Card和Button外壳。packages/dynamic-form/src/consumer/effects/:通过 handler 系统应用 effect 返回值。packages/dynamic-form/src/consumer/render/componentRegistry.tsx:提供内置组件和自定义组件注册能力。
数据流
- 可选 Adapter 把外部输入归一化为
ModuleFormConfig。 - 可选 Compiler 展开字段模块、编译字段/group rules,并生成标准
FormConfig与组件注册表。 - 用户通过
DynamicForm传入手写FormConfig,或通过CompiledDynamicForm传入 compiler 产物。 DynamicForm把引擎层参数传给DynamicFormProvider,把 UI 参数传给FormContent。useStoreInit调用processFormConfig(formConfig)。- 配置处理把
nodes、fields和groups归一化为节点树,生成依赖图、node/container/field registry、初始值和初始化后的字段/container 状态。 - reducer 接收
INIT,保存节点结构、meta、配置处理信息和动态 UI 配置。 DynamicFormProvider用effectMap初始化form-chain-effect。FormContent基于 reducer state 计算一次runtimeState。- 渲染、提交校验、字段变更校验和隐藏字段参与策略共同使用这份
runtimeState。 - 用户输入触发 runtime 过滤后的校验,再把变更值交给 effect engine。
- effect 返回值进入
applyEffectResult,handler 通过 form adapter 更新表单值,或更新字段 meta、分组 meta、动态 UI 配置。
状态归属
Form runtime 负责;默认实现是 Ant Design Form:
- 字段值
- 校验 errors 和 warnings
- touched 和 validating 状态
- 提交时的数据读取
DynamicForm reducer 负责:
- 平铺字段状态
- container/group 字段状态
- 节点状态与根节点顺序
- 字段行为 meta 和渲染 meta
- container/group 行为 meta
- 配置处理信息
- 动态 UI 配置
- initialized 标记
reducer 不维护重复的 values store。更新值的 effect handler 应调用上下文提供的 setFieldValue 或 formAdapter。
分层职责
- Core Adapter Layer:只负责把外部输入转换为
ModuleFormConfig,不决定 renderer 行为。 - Core Module / Compiler Layer:展开领域字段模块、装配 flat/grouped/mixed/nodes 结构,并输出标准
FormConfig。 - Core Rule Layer:把同步声明式规则编译为标准 effects,不替代 effect engine 或 Ant Design validation。
- Core Config Layer:把 flat/grouped/mixed/nodes
FormConfig归一化为节点树和标准化运行时输入。 - State Layer:在 React/AntD 包中保存初始化后的字段/container 结构和 meta,并兼容旧的 flat meta key。
- Runtime Layer:core 提供纯 resolver,React/AntD 包通过
useRuntimeState为 UI 消费同一份 Runtime snapshot。 - Consumer Layer:连接 Provider、form adapter、renderer adapter、hooks、effect 结果处理和组件注册。
- Shared Layer:core 存放纯公共类型和工具,React/AntD 包补充 React context、初始化检查和 UI 相关类型。
维护约束
- 字段查找应使用
configProcessInfo.fieldRegistry,因为字段可能是平铺字段,也可能在任意 container 内。 FormContent应对每个 state snapshot 只计算一次 Runtime。- 校验必须通过
runtimeState.fields[fieldId].validatable过滤。 - 隐藏字段默认不参与提交,除非字段配置显式保留值。
- Container 可见性必须沿父链传递给所有后代字段和 container。
- render hooks 可以绕过默认渲染,因此修改扩展行为时要谨慎。
- Adapter、Compiler 和 Rule Engine 应保持在 React runtime 之外,不直接维护 Form 实例或 reducer state。