@schemx/vue 1.0.0 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (121) hide show
  1. package/README.md +509 -324
  2. package/dist/analyze.html +1 -1
  3. package/dist/bridge/fieldBridge.d.ts +12 -0
  4. package/dist/bridge/fieldBridge.d.ts.map +1 -1
  5. package/dist/bridge/formBridge.d.ts +35 -2
  6. package/dist/bridge/formBridge.d.ts.map +1 -1
  7. package/dist/bridge/formInstance.d.ts +24 -4
  8. package/dist/bridge/formInstance.d.ts.map +1 -1
  9. package/dist/bridge/helpers.d.ts +8 -0
  10. package/dist/bridge/helpers.d.ts.map +1 -1
  11. package/dist/bridge/index.d.ts +2 -3
  12. package/dist/bridge/index.d.ts.map +1 -1
  13. package/dist/bridge/types.d.ts +97 -9
  14. package/dist/bridge/types.d.ts.map +1 -1
  15. package/dist/bridge/viewSchemaBridge.d.ts +14 -1
  16. package/dist/bridge/viewSchemaBridge.d.ts.map +1 -1
  17. package/dist/components/Button/index.d.ts.map +1 -1
  18. package/dist/components/Button/index.vue.d.ts +12 -0
  19. package/dist/components/Button/index.vue.d.ts.map +1 -1
  20. package/dist/components/Button/types.d.ts +15 -5
  21. package/dist/components/Button/types.d.ts.map +1 -1
  22. package/dist/components/Col/index.d.ts +27 -5
  23. package/dist/components/Col/index.d.ts.map +1 -1
  24. package/dist/components/ConfigProvider/index.d.ts +40 -7
  25. package/dist/components/ConfigProvider/index.d.ts.map +1 -1
  26. package/dist/components/Dynamic/index.d.ts +27 -17
  27. package/dist/components/Dynamic/index.d.ts.map +1 -1
  28. package/dist/components/Field/index.d.ts +13 -2
  29. package/dist/components/Field/index.d.ts.map +1 -1
  30. package/dist/components/Field/slot.d.ts +34 -10
  31. package/dist/components/Field/slot.d.ts.map +1 -1
  32. package/dist/components/Group/index.d.ts +37 -8
  33. package/dist/components/Group/index.d.ts.map +1 -1
  34. package/dist/components/Group/slot.d.ts +36 -9
  35. package/dist/components/Group/slot.d.ts.map +1 -1
  36. package/dist/components/Icon/index.d.ts +29 -0
  37. package/dist/components/Icon/index.d.ts.map +1 -0
  38. package/dist/components/Row/index.d.ts +30 -0
  39. package/dist/components/Row/index.d.ts.map +1 -0
  40. package/dist/components/SchemaList/index.d.ts +22 -12
  41. package/dist/components/SchemaList/index.d.ts.map +1 -1
  42. package/dist/components/Wrapper/index.vue.d.ts +6 -0
  43. package/dist/components/Wrapper/index.vue.d.ts.map +1 -1
  44. package/dist/config/defaultVueSchemaConfig.d.ts +62 -0
  45. package/dist/config/defaultVueSchemaConfig.d.ts.map +1 -0
  46. package/dist/config/index.d.ts +12 -2
  47. package/dist/config/index.d.ts.map +1 -1
  48. package/dist/config/vueConfig.d.ts +14 -3
  49. package/dist/config/vueConfig.d.ts.map +1 -1
  50. package/dist/context/configProviderContext.d.ts +66 -0
  51. package/dist/context/configProviderContext.d.ts.map +1 -0
  52. package/dist/context/fieldContext.d.ts +11 -0
  53. package/dist/context/fieldContext.d.ts.map +1 -0
  54. package/dist/context/formContext.d.ts +167 -0
  55. package/dist/context/formContext.d.ts.map +1 -0
  56. package/dist/context/index.d.ts +18 -0
  57. package/dist/context/index.d.ts.map +1 -0
  58. package/dist/form.d.ts +10 -2
  59. package/dist/form.d.ts.map +1 -1
  60. package/dist/hocs/withRemoteOptions.d.ts +6 -2
  61. package/dist/hocs/withRemoteOptions.d.ts.map +1 -1
  62. package/dist/hooks/index.d.ts +23 -15
  63. package/dist/hooks/index.d.ts.map +1 -1
  64. package/dist/hooks/useDictionary.d.ts +32 -9
  65. package/dist/hooks/useDictionary.d.ts.map +1 -1
  66. package/dist/hooks/useField.d.ts +7 -0
  67. package/dist/hooks/useField.d.ts.map +1 -1
  68. package/dist/hooks/useForm.d.ts +4 -16
  69. package/dist/hooks/useForm.d.ts.map +1 -1
  70. package/dist/hooks/useFormSelector.d.ts.map +1 -1
  71. package/dist/hooks/useViewSchemas.d.ts +26 -2
  72. package/dist/hooks/useViewSchemas.d.ts.map +1 -1
  73. package/dist/index.cjs +1 -1
  74. package/dist/index.cjs.map +1 -1
  75. package/dist/index.d.ts +35 -13
  76. package/dist/index.d.ts.map +1 -1
  77. package/dist/index.mjs +684 -357
  78. package/dist/index.mjs.map +1 -1
  79. package/dist/style.css +1 -1
  80. package/dist/types/definition.d.ts +248 -0
  81. package/dist/types/definition.d.ts.map +1 -0
  82. package/dist/types/dictionary.d.ts +9 -3
  83. package/dist/types/dictionary.d.ts.map +1 -1
  84. package/dist/types/field.d.ts +93 -21
  85. package/dist/types/field.d.ts.map +1 -1
  86. package/dist/types/form.d.ts +82 -6
  87. package/dist/types/form.d.ts.map +1 -1
  88. package/dist/types/icon.d.ts +15 -0
  89. package/dist/types/icon.d.ts.map +1 -0
  90. package/dist/types/index.d.ts +2 -15
  91. package/dist/types/index.d.ts.map +1 -1
  92. package/dist/types/layout.d.ts +89 -13
  93. package/dist/types/layout.d.ts.map +1 -1
  94. package/dist/utils/diff.d.ts +3 -6
  95. package/dist/utils/diff.d.ts.map +1 -1
  96. package/dist/utils/dynamic.d.ts +6 -2
  97. package/dist/utils/dynamic.d.ts.map +1 -1
  98. package/dist/utils/equal.d.ts +2 -2
  99. package/dist/utils/helpers.d.ts +26 -2
  100. package/dist/utils/helpers.d.ts.map +1 -1
  101. package/dist/utils/index.d.ts +19 -4
  102. package/dist/utils/index.d.ts.map +1 -1
  103. package/dist/utils/layout.d.ts +17 -0
  104. package/dist/utils/layout.d.ts.map +1 -0
  105. package/dist/utils/rendererProvider.d.ts +10 -3
  106. package/dist/utils/rendererProvider.d.ts.map +1 -1
  107. package/dist/utils/validation.d.ts +6 -2
  108. package/dist/utils/validation.d.ts.map +1 -1
  109. package/package.json +2 -2
  110. package/dist/config/appConfig.d.ts +0 -19
  111. package/dist/config/appConfig.d.ts.map +0 -1
  112. package/dist/config/providerConfig.d.ts +0 -22
  113. package/dist/config/providerConfig.d.ts.map +0 -1
  114. package/dist/hooks/provideFieldContext.d.ts +0 -40
  115. package/dist/hooks/provideFieldContext.d.ts.map +0 -1
  116. package/dist/hooks/provideFormConfigContext.d.ts +0 -71
  117. package/dist/hooks/provideFormConfigContext.d.ts.map +0 -1
  118. package/dist/hooks/provideFormContext.d.ts +0 -26
  119. package/dist/hooks/provideFormContext.d.ts.map +0 -1
  120. package/dist/utils/colProvider.d.ts +0 -20
  121. package/dist/utils/colProvider.d.ts.map +0 -1
package/README.md CHANGED
@@ -1,8 +1,8 @@
1
1
  # @schemx/vue
2
2
 
3
- `@schemx/vue` 将 `@schemx/core` 的表单实例和 ViewSchemas 渲染为 Vue 3 组件树。它不绑定具体 UI 组件库,适合接入业务组件、设计系统或新的 UI adapter。
3
+ `@schemx/vue` 将 `@schemx/core` 的表单实例和 ViewSchemas 渲染为 Vue 3 组件树,包含 Group、Dependency 和 Dynamic 数组的递归渲染。它不绑定具体 UI 组件库,适合接入业务组件、设计系统或新的 UI adapter。
4
4
 
5
- 如果项目使用 Vant,推荐直接安装 [`@schemx/vant`](../vant)。该包已经注册常用的移动端表单 Renderer。
5
+ 如果项目使用 Vant 或 Element Plus,可分别安装 [`@schemx/vant`](../vant) 或 [`@schemx/element-plus`](../element-plus),直接使用已注册的表单 Renderer。
6
6
 
7
7
  适用于使用自研组件或设计系统的 Vue 3 项目。该包提供表单组件、响应式 Hook 和 Renderer 注册机制,但不内置具体输入控件;每种 `componentType` 都需要由应用自行注册 Renderer。
8
8
 
@@ -20,6 +20,8 @@ ESM 入口 `@schemx/vue` 会通过入口模块自动加载基础样式,常规
20
20
  import "@schemx/vue/style.css"
21
21
  ```
22
22
 
23
+ Vue 包的样式只定义 Row/Col、Field、Group 和状态类的通用结构;移动端卡片、分隔线和桌面端间距由对应 UI 适配包补充。UI 适配包的手动样式应在 `@schemx/vue/style.css` 之后导入。
24
+
23
25
  不要从 `src/styles` 或 `dist` 的内部路径导入样式;包的 `exports` 只公开根入口和 `./style.css`。
24
26
 
25
27
  ## 快速开始
@@ -95,11 +97,13 @@ console.log(Schemx === schemxForm) // true
95
97
  | `readonly` | `boolean` | `undefined` | 表单级只读默认值;字段自身配置优先 |
96
98
  | `disabled` | `boolean` | `undefined` | 表单级禁用默认值;字段自身配置优先 |
97
99
  | `visible` | `boolean` | `true` | 表单级可见性默认值;字段自身配置优先 |
98
- | `labelIcon` | `string` | `undefined` | 表单级标签图标默认值;会进入字段 ViewSchema,具体是否渲染取决于适配组件 |
99
- | `labelAlign` | `"left" \| "center" \| "right"` | `undefined` | 表单级标签对齐默认值;字段自身配置优先,均未配置时为 `"left"` |
100
+ | `labelIcon` | `string \| Component` | `undefined` | 表单级标签图标默认值;字符串传给 Icon Adapter,Component 直接渲染 |
101
+ | `iconComponent` | `Component` | `undefined` | 当前 Form 使用的 Icon Adapter;优先级高于 ConfigProvider、App 和全局注册 |
102
+ | `labelAlign` | `"left" \| "center" \| "right"` | `undefined` | 表单级标签对齐默认值;字段自身配置优先,均未配置时为 `"right"` |
100
103
  | `labelPosition` | `"left" \| "top" \| "right"` | `undefined` | 表单级标签位置默认值;字段自身配置优先,均未配置时为 `"left"` |
101
104
  | `labelWidth` | `string` | `undefined` | 表单级标签宽度默认值;字段自身配置优先,均未配置时为 `"auto"` |
102
- | `contentAlign` | `"left" \| "center" \| "right"` | `undefined` | 表单级内容对齐默认值;用于解析 Renderer `align`,字段自身配置优先 |
105
+ | `contentAlign` | `"left" \| "center" \| "right"` | `undefined` | 表单级内容区域对齐配置;字段自身配置优先,默认为 `"left"`;只读字段自动为 `"right"` |
106
+ | `errorAlign` | `"left" \| "center" \| "right"` | `undefined` | 表单级校验错误对齐配置;字段自身配置优先,均未配置时为 `"left"` |
103
107
  | `validationTrigger` | `ValidationTrigger \| ValidationTrigger[]` | `["blur", "change"]` | 表单级校验触发方式默认值;字段自身配置优先 |
104
108
  | `colon` | `boolean` | `undefined` | 表单级标签冒号默认值;字段自身配置优先,均未配置时为 `true` |
105
109
  | `onFinish` | `(values: Readonly<T>) => void \| Promise<void>` | `undefined` | `submit()` 校验通过后的回调 Prop |
@@ -109,25 +113,62 @@ console.log(Schemx === schemxForm) // true
109
113
  | `onValuesChange` | `(changedValues, latestSnapshot) => void` | `undefined` | 字段值变化后的回调 Prop |
110
114
  | `onFieldsChange` | `(changedFields, allFields) => void` | `undefined` | 字段路径变化后的回调 Prop |
111
115
  | `onRuleError` | `FormCallbackOptions<T>["onRuleError"]` | `undefined` | 规则解析异常回调;内部创建实例时当前不会透传,需在外部 `form` 实例上配置 |
112
- | `lifecycleHooks` | `FormLifecycleOptions["lifecycleHooks"]` | `undefined` | Runtime 生命周期钩子 |
116
+ | `lifecycleHooks` | `FormLifecycleOptions["lifecycleHooks"]` | `undefined` | Core Form 的 Runtime 生命周期钩子;当前 `<Schemx>` 创建内部实例时不会透传,需通过 `useForm()` 或 `createForm()` 配置。 |
113
117
  | `schedulerOptions` | `SchedulerOptions` | `undefined` | Scheduler 时间片与 idle 队列配置 |
114
118
  | `validationConcurrency` | `number` | `8` | 整表校验时同时运行的字段数 |
115
119
  | `loading` | `boolean` | `undefined` | 覆盖内置操作区显示的提交状态,不改变 Core 的真实提交状态 |
116
120
  | `submitter` / `resetter` | `boolean \| SchemxFormActionConfig` | `true` | 控制内置提交 / 重置按钮;默认渲染,设为 `false` 隐藏,配置可设置 `text` 和 `buttonProps` |
117
121
  | `class` | `string` | `""` | 添加到根 `.schemx` 元素的类名 |
118
122
  | `style` | `StyleValue` | `{}` | 绑定到根 `.schemx` 元素 |
123
+ | `row` | `SchemxRowConfig` | `undefined` | 根级 Row 配置;Group/Dynamic 未显式配置时继承该默认值 |
124
+ | `col` | `SchemxColConfig` | `{ span: 24 }` | 字段级默认 Col 配置;字段自身的 `col` 优先 |
125
+
126
+ 上述 Schema 默认配置都会参与字段规范化:Core 负责 `required`、`readonly`、`disabled`、`visible` 和校验触发方式,Vue 适配层负责标签、内容对齐、冒号、必填标记和 `schemaConfig.row` 等布局展示默认值。`schemaConfig.row` 可作为根级、Group 和 Dynamic Row 的默认配置,Form 顶层 `row` 仍拥有更高优先级。Registry、默认 Renderer 和 `validatorAdapters` 则按表单显式配置 → 当前 App 安装配置 → Vue 模块级 Registry → Core 模块级配置 → Core 内置默认值解析。必填只能通过 `required: true` 或 `RequiredOptions` 表达;普通 `rules` 只负责执行校验,不会显示必填星号。传入 `form` 时,`initialValues`、Registry 和所有表单回调都由外部实例的创建者配置;组件不会用同名 Props 重建 Core Form,但会通过 Vue bridge 包装该实例,并同步 `schemas` 与组件声明的 schema 配置。
127
+
128
+ `ConfigProvider` 的 `schemaConfig`、`row`、`colComponent` 和 `iconComponent` 更新会同步到已挂载的内部 `<Schemx>`;Registry、校验 adapter 和默认 Renderer 类型仍在 Form 创建时解析。
129
+
130
+ Icon Adapter 只能通过 `iconComponent` 传入。Adapter 接收 `{ icon }` Props,字符串的具体解释由业务或 UI 适配包决定;未配置 Adapter 时字符串回退为普通文本。
131
+
132
+ ### Row / Col 布局
119
133
 
120
- 上述 Schema 默认配置都会参与 core 的字段规范化,通常按字段配置 → 表单 Prop → core 固定默认值合并。Registry、默认 Renderer 和 `validatorAdapters` 则按表单显式配置 当前 App 安装配置 Vue 模块级 Registry → Core 模块级配置 → Core 内置默认值解析。必填只能通过 `required: true` `RequiredOptions` 表达;普通 `rules` 只负责执行校验,不会显示必填星号。传入 `form` 时,`initialValues`、Registry 和所有表单回调都由外部实例的创建者配置;组件不会用同名 Props 重建 Core Form,但会通过 Vue bridge 包装该实例,并同步 `schemas` 与组件声明的 schema 配置。
134
+ Form 使用 `row` 配置根级 Row;Group Dynamic Schema 使用 `row` 配置各自的子级 Row,Dynamic 会为每个数组 item 创建一行。Field 使用 `col` 配置自身的 Col:
121
135
 
122
- `ConfigProvider` `schemaConfig` `colComponent` 更新会同步到已挂载的内部 `<Schemx>`;Registry、校验 adapter 和默认 Renderer 类型仍在 Form 创建时解析。
136
+ `row.gutter` 支持 CSS padding shorthand:单个数字、`[上下, 左右]` 二元组或 `[上, 右, 下, 左]` 四元组。
137
+
138
+ ```ts
139
+ const schemas = [
140
+ {
141
+ name: "title",
142
+ label: "标题",
143
+ componentType: "input",
144
+ col: { span: 12 },
145
+ },
146
+ {
147
+ label: "基本信息",
148
+ row: { gutter: 12 },
149
+ children: [
150
+ {
151
+ name: "description",
152
+ label: "描述",
153
+ componentType: "input",
154
+ col: { span: 8 },
155
+ },
156
+ ],
157
+ },
158
+ ]
159
+ ```
123
160
 
124
- 当未显式传入 `rendererRegistry` 时,Vue `useForm()` 会使用全局 Registry;该 Registry 默认以 `input` 作为 fallback。因此若要让 `<Schemx :default-renderer-type="...">` 生效,应传入独立 Registry,或直接对 Vue 导出的全局 Registry 调用 `setFallback()`。传入外部 `form` 时,Renderer 配置由该实例决定。
161
+ 旧的 `layout` 字段以及 `SchemxLayout` 类型进入弃用期。兼容期内 Field `col` 优先于旧 `layout`;新代码应迁移到 `row` / `col`。
162
+
163
+ `Col` 组件的旧 `component` Prop 保留为弃用兼容入口;新代码请在 Form 或 `ConfigProvider` 配置 `colComponent`。
164
+
165
+ 当未显式传入 `rendererRegistry` 时,Vue `useForm()` 会使用全局 Registry;该 Registry 默认以 `input` 作为 fallback。因此若要让 `<Schemx :default-renderer-type="...">` 生效,应传入独立 Registry,或直接对 Vue 导出的全局 Registry 调用 `setFallback()`。传入外部 `form` 时,Renderer 配置由该实例决定。Row/Col 渲染器从 Form Context 读取 `rowComponent` / `colComponent`;底层 Row/Col 组件不再接收这两个组件 Props。
125
166
 
126
167
  ### `v-model`、`initialValues` 与事件
127
168
 
128
169
  `initialValues` 是内部 Store 的初始快照和 `reset()` 基准。`modelValue` 按 Vue 约定作为输入和输出:
129
170
 
130
- - 创建内部实例时,非空 `modelValue` 会覆盖同名 `initialValues` 字段,作为初始快照。
171
+ - 创建内部实例时,非空 `modelValue` 会整体作为内部表单初始值,优先于 `initialValues`。
131
172
  - 外部替换 `modelValue` 后,组件会调用 `setFieldsValue()` 同步内部表单。
132
173
  - 传入外部 `form` 时,非空 `modelValue` 会在组件挂载时先写入该实例;空对象仍视为未提供。
133
174
  - 内部或外部 `form` 的字段变化都会发出 `update:modelValue`,值为最新表单快照;同步来自 `modelValue` 的变化不会重复发出该事件。
@@ -136,7 +177,7 @@ console.log(Schemx === schemxForm) // true
136
177
  - 传入外部 `form` 时,`onReset` 与 `onLoadingChange` 同样不会重新配置该实例;请在创建该实例时传入回调。
137
178
  - `onFinish`、`onFinishFailed`、`onValuesChange` 和 `onFieldsChange` 是声明过的回调 Props,不在 `defineEmits` 的事件列表中。模板中的 `@finish` 等写法会按 Vue listener Prop 规则映射到这些 Props,但 TypeScript 用户更适合显式传回调。
138
179
 
139
- 内部表单模式还存在一个 `onFinish` 等待边界:组件传给 core 的包装函数会调用 `props.onFinish(values)`,但没有 `return` `await` 其返回值。因此 `submit()` 只等待这层立即完成的包装 Promise,不等待业务 `onFinish` 返回的异步任务;该任务后续 reject 也不会沿 `submit()` 传播。业务回调若在返回 Promise 前同步抛错,包装函数会转为 rejected Promise,core 的 `submit()` 仍会收到该拒绝。传入外部 `form` 时组件不会安装这层包装,等待和错误传播完全取决于外部实例创建者配置的回调;core `createForm()` 本身会 `await` 直接传给它的 `onFinish`。
180
+ 内部表单模式会把 `props.onFinish(values)` 的返回值交给 Core,因此 `submit()` 会等待业务回调返回的 Promise;业务回调同步抛错或异步拒绝时,`submit()` 也会拒绝。传入外部 `form` 时组件不会重新配置这层回调,等待和错误传播完全取决于外部实例创建者;Core `createForm()` 同样会等待直接传入的 `onFinish`。
140
181
 
141
182
  唯一通过 `defineEmits` 声明的组件事件如下:
142
183
 
@@ -152,12 +193,12 @@ console.log(Schemx === schemxForm) // true
152
193
 
153
194
  | Slot 名称 | Slot Props | 行为 |
154
195
  | ------------------- | ------------------------------------- | -------------------------------------------------------------------------------------------------------- |
155
- | `{name}` | `SchemxFieldSlotProps` | 替换 Field wrapper 内的默认内容;保留 wrapper、其 class/style 和透传属性 |
156
- | `{name}Label` | `SchemxFieldSlotProps` | 替换标签区域 |
157
- | `{name}Before` | `SchemxFieldSlotProps` | 渲染在 Renderer 前 |
196
+ | `{name}` | `SchemxFieldSlotProps` | 替换标签和控件主体;保留 wrapper、其 class/style、透传属性及 Before / Error / After 区域 |
197
+ | `{name}Label` | `SchemxFieldSlotProps` | 替换 `schemx-field__label` 内部内容,保留标签宽度与对齐;图标、必填标记和冒号由插槽自行处理 |
198
+ | `{name}Before` | `SchemxFieldSlotProps` | 渲染在整个字段主体前,与主体同级 |
158
199
  | `{name}Content` | `SchemxFieldContentSlotProps` | 替换控件内容区域;额外提供默认 Renderer 的 `columnElement` |
159
- | `{name}After` | `SchemxFieldSlotProps` | 渲染在 Renderer 后、错误区域前 |
160
- | `{name}Error` | `SchemxFieldErrorSlotProps` | 替换错误区域;额外提供当前错误列表 `errors` |
200
+ | `{name}Error` | `SchemxFieldErrorSlotProps` | 替换 `schemx-field__error` 内部内容,保留错误样式与对齐;额外提供当前错误列表 `errors` |
201
+ | `{name}After` | `SchemxFieldSlotProps` | 渲染在错误区域后,与主体同级 |
161
202
  | `{name}:{slotName}` | 原样传给 Renderer | 去掉 `{name}:` 前缀后作为 Renderer 命名 Slot;同一数组路径的前缀为 `user.name:`,例如 `user.name:prefix` |
162
203
  | `{groupKey}Header` | `SchemxGroupSlotProps` | 替换分组 Header 内部内容;保留默认的无障碍与折叠容器 |
163
204
  | `{groupKey}Label` | `SchemxGroupSlotProps` | 替换默认分组标题;保留默认折叠箭头 |
@@ -169,18 +210,20 @@ console.log(Schemx === schemxForm) // true
169
210
 
170
211
  字段 Slot 的规范公共参数为 `{ schema, componentProps, value, field, form }`;不再把 Schema 或 Renderer Props 展开到 Slot 参数顶层。这样区域专属参数始终清晰可辨:`Content` 增加 `columnElement`,`Error` 增加 `errors`。这些公开类型均可从 `@schemx/vue` 导入。
171
212
 
213
+ 字段顺序为 `Before → 主体(Label + Content,或整体插槽)→ Error → After`。整体插槽接管输入时,调用 `componentProps.onChange(value)` 和 `componentProps.onBlur(value)` 可复用字段回调与校验触发;只调用 `field.setValue(value)` 不会触发这些处理。`Label` 插槽已位于 `<label>` 内,无需再嵌套 `<label>`。`Content` 插槽位于 `schemx-field__content` 内,可用 `<component :is="columnElement" />` 渲染默认控件。`Error` 插槽在无错误时也会调用,可根据 `errors.length` 控制内容。
214
+
172
215
  ```vue
173
216
  <Schemx :schemas="schemas">
174
- <template #nicknameLabel="schema">
217
+ <template #nicknameLabel="{ schema }">
175
218
  <strong>{{ schema.label }}</strong>
176
219
  </template>
177
220
 
178
221
  <template #nicknameBefore>
179
- <span>@</span>
222
+ <small>昵称将展示在个人主页</small>
180
223
  </template>
181
224
 
182
225
  <template #nicknameAfter="{ value }">
183
- <small>{{ String(value).length }}/20</small>
226
+ <small>{{ String(value ?? "").length }}/20</small>
184
227
  </template>
185
228
 
186
229
  <template #nicknameError="{ errors }">
@@ -265,13 +308,29 @@ app.use(Schemx, {
265
308
  })
266
309
  ```
267
310
 
268
- 安装配置属于当前 Vue App;不同 App 可以使用不同的 Registry、字段默认值、默认 renderer 类型和校验 adapter,适用于多应用和 SSR 隔离场景。配置优先级为表单显式配置、当前 App 安装配置、Vue 包默认 Registry、Core 模块级配置、Core 内置默认值。`validatorAdapters` 按该顺序累积;同 ID adapter 需要通过 `{ adapter, override: true }` 显式覆盖。`app.use()` 不会调用 Core 的模块级 `configureSchemx()`;该 API 仍可作为 Vue 与直接 `createForm()` 的低优先级基线。可安装组件还挂载了静态属性 `Schemx.Field`;`Group` 仅作为根入口命名导出,不是静态属性。
311
+ 安装配置属于当前 Vue App;不同 App 可以使用不同的 Registry、字段默认值、默认 renderer 类型和校验 adapter,适用于多应用和 SSR 隔离场景。配置优先级为表单显式配置、当前 App/Provider 配置、Vue/Core 模块级配置和 Core 内置默认值。UI 适配包导出的 Registry、布局组件和字段默认值需要通过 Form Props 或 `ConfigProvider` 显式传入。`validatorAdapters` 按该顺序合并,不同配置层的同 ID adapter 由高优先级配置覆盖,同一配置层内的重复 ID 仍需通过 `{ adapter, override: true }` 显式覆盖。`app.use()` 不会调用 Core 的模块级 `configureSchemx()`;该 API 仍可作为 Vue 与直接 `createForm()` 的业务基线。可安装组件还挂载了静态属性 `Schemx.Field`;`Group` 仅作为根入口命名导出,不是静态属性。
269
312
 
270
313
  `SchemxFormProps` 和 Vue 层 `FieldInstance` 也会从 `@schemx/vue` 根入口导出;业务代码通常仍可直接从组件或 Hook 调用处推导类型,不需要依赖深层路径。
271
314
 
315
+ 需要对组件树内多个表单统一设置展示默认值时,可以使用 `ConfigProvider`:
316
+
317
+ ```vue
318
+ <script setup lang="ts">
319
+ import Schemx, { ConfigProvider } from "@schemx/vue"
320
+ </script>
321
+
322
+ <template>
323
+ <ConfigProvider :schema-config="{ readonly: true, showRequiredMark: false }">
324
+ <Schemx :schemas="schemas" />
325
+ </ConfigProvider>
326
+ </template>
327
+ ```
328
+
329
+ `ConfigProvider` 不渲染额外 DOM;子级 Provider 的非空配置会覆盖父级同名配置。`schemaConfig`、`row`、`rowComponent`、`colComponent` 和 `iconComponent` 的变化会同步到已挂载的内部 `<Schemx>`,Registry、校验 adapter 和默认 Renderer 类型只在 Form 创建时解析。
330
+
272
331
  ## Schema 写法
273
332
 
274
- 根入口从 `@schemx/core` 传递导出 `SchemxField<T>`。它是普通字段、分组和动态依赖子树的联合类型。
333
+ 根入口从 `@schemx/core` 传递导出 `SchemxField<T>`。它是普通字段、分组、动态依赖子树和动态数组字段的联合类型。
275
334
 
276
335
  ### 普通字段
277
336
 
@@ -292,9 +351,7 @@ const schemas: SchemxField<Values>[] = [
292
351
  required: true,
293
352
  showRequiredMark: false,
294
353
  validationTrigger: ["change", "blur"],
295
- componentProps: {
296
- align: "left",
297
- },
354
+ componentProps: {},
298
355
  },
299
356
  ]
300
357
  ```
@@ -312,11 +369,12 @@ const schemas: SchemxField<Values>[] = [
312
369
  | `required`、`readonly`、`disabled`、`visible` | 否 | 字段展示和交互状态;`required` 同时参与默认必填校验与星号默认展示 |
313
370
  | `showRequiredMark` | 否 | 只控制 label 前星号:未设置时等同于 `Boolean(required)`;设为 `true` 可显示非必填字段星号,设为 `false` 可隐藏必填字段星号;禁用或只读时始终隐藏,且不会影响校验 |
314
371
  | `initialValue` | 否 | 字段挂载时的初始值和 `reset()` 还原值 |
372
+ | `preserve` | 否 | Schema 移除或字段改名时是否保留字段值和状态;默认保留,设为 `false` 时清理旧路径 |
315
373
  | `rules` | 否 | 单条或多条校验规则,支持 Standard Schema 与内置规则名 |
316
- | `labelIcon`、`labelAlign`、`labelPosition`、`labelWidth` | 否 | 标签展示配置 |
317
- | `contentAlign`、`colon` | 否 | 内容对齐和冒号配置 |
374
+ | `labelIcon`、`labelAlign`、`labelPosition`、`labelWidth` | 否 | 标签展示配置;`labelIcon` 支持字符串或 Vue Component |
375
+ | `contentAlign`、`errorAlign`、`colon` | 否 | 内容、校验错误对齐和冒号配置 |
318
376
  | `validationTrigger` | 否 | `change`、`blur` 等校验触发时机 |
319
- | `onChange`、`onBlur` | 否 | 类型中存在的顶层回调;当前 Vue `Field` 不调用它们,Renderer 事件说明见后文 |
377
+ | `onChange`、`onBlur` | 否 | 字段值变化和失焦时由 Vue `Field` 调用;Renderer 事件说明见后文 |
320
378
  | `class`、`style` | 否 | Vue 通过声明合并增加,运行时分别应用到字段容器的 class 和内联 style,发布根声明会自动带入该 augmentation |
321
379
  | `key` | 否 | 框架字段;业务方通常不要设置 |
322
380
 
@@ -373,14 +431,61 @@ const dependency: SchemxField<Values> = {
373
431
 
374
432
  `renderer` 可以同步或异步返回新的 `SchemxField<T>[]`;`context.abortSignal` 用于取消已经过期的异步依赖计算。该 `AbortSignal` 属于 Core 的 Dependency renderer,和后文 `useDictionary` 的请求行为不同。
375
433
 
434
+ ### 动态数组
435
+
436
+ Dynamic 数组字段使用必填的 `key`、数组路径 `name` 和行模板 `item`。`item` 中的普通字段和 Group 使用相对路径,Vue 会根据当前数组索引展开并递归渲染每一行;数组行增删或移动通过 Core Form 的 `setFieldValue(path, updater)` 完成。
437
+
438
+ ```ts
439
+ import { useForm, type SchemxField } from "@schemx/vue"
440
+
441
+ type Member = {
442
+ name: string
443
+ role: "developer" | "designer"
444
+ }
445
+
446
+ type TeamValues = {
447
+ members: Member[]
448
+ }
449
+
450
+ const schemas: SchemxField<TeamValues>[] = [
451
+ {
452
+ key: "members",
453
+ name: "members",
454
+ label: "团队成员",
455
+ item: [
456
+ {
457
+ key: "member",
458
+ label: "成员信息",
459
+ children: [
460
+ { name: "name", label: "姓名", componentType: "input" },
461
+ { name: "role", label: "角色", componentType: "text" },
462
+ ],
463
+ },
464
+ ],
465
+ },
466
+ ]
467
+
468
+ const form = useForm<TeamValues>({
469
+ initialValues: { members: [{ name: "张三", role: "developer" }] },
470
+ schemas,
471
+ })
472
+
473
+ form.setFieldValue("members", (members) => [
474
+ ...(members ?? []),
475
+ { name: "李四", role: "designer" },
476
+ ])
477
+ ```
478
+
479
+ Dynamic 容器的 `visible`、`readonly`、`disabled` 和 `dependencies` 会传递到每行后代字段。行内模板可以包含普通字段、Group 和 Dependency,但不能嵌套 Dynamic;行内 Dependency 的 `to` 使用完整表单路径,`renderer` 返回的子 Schema 使用当前行相对路径。Dynamic 组件是 `Schemx` 内部实现,不是根入口的独立导出。Dynamic 的每行子 Schema 统一由 SchemaList 回调渲染,以保持行 key、Col 和插槽透传一致。
480
+
376
481
  ## Dictionary
377
482
 
378
- `SchemxDictionary<T, R>` 描述由函数加载的选项列表:`T` 是完整表单值类型,`R` 是 `api` 的原始返回类型,并会传给 `formatter`。
483
+ `SchemxDictionary<TValues, TResponse, TOption>` 描述由函数加载的选项列表:`TValues` 是完整表单值类型,`TResponse` 是 `api` 的原始返回类型,`TOption` 是格式化后的选项类型。`api` 声明第三个参数时还会收到当前请求的 `AbortSignal`。
379
484
 
380
485
  ```ts
381
- interface SchemxDictionary<T extends Values = Values, R = any> {
486
+ interface SchemxDictionary<T extends Values = Values, R = unknown, O = unknown> {
382
487
  api: (values: T, form: SchemxInstance<T>, signal?: AbortSignal) => R | Promise<R>
383
- formatter?: (res: Awaited<R>, form: SchemxInstance<T>) => any[] | Promise<any[]>
488
+ formatter?: (res: Awaited<R>, form: SchemxInstance<T>) => O[] | Promise<O[]>
384
489
  dependsOn?: NamePath<T>[]
385
490
  shouldFetch?: (values: T) => boolean
386
491
  immediate?: boolean
@@ -388,29 +493,29 @@ interface SchemxDictionary<T extends Values = Values, R = any> {
388
493
  retryCount?: number
389
494
  retryInterval?: number
390
495
  onError?: (error: Error, form: SchemxInstance<T>) => void
391
- onSuccess?: (data: any[], form: SchemxInstance<T>) => void
496
+ onSuccess?: (data: O[], form: SchemxInstance<T>) => void
392
497
  onDepsChange?: (values: T, form: SchemxInstance<T>) => void
393
498
  }
394
499
  ```
395
500
 
396
- | 字段 | 默认值 | 真实行为 |
397
- | ------------------- | ------------------- | -------------------------------------------------------------------------------------------------- |
398
- | `api` | 必填 | 接收加载开始时的完整表单快照和实例;支持同步或异步返回 |
399
- | `formatter` | 直接使用 `api` 结果 | 在请求成功后转换结果;支持异步,返回值应为数组 |
400
- | `dependsOn` | `undefined` | 通过 `useWatchFields` 监听这些字段;变化时执行依赖回调、可选重置和重新加载 |
401
- | `shouldFetch` | 总是加载 | 每次加载前判断;返回 `false` 时跳过 `api`、清空 `list` 并结束加载状态 |
402
- | `immediate` | `true` | 组件 `onMounted` 时是否自动调用一次 `loadDict()`;不影响依赖变化或手动刷新 |
403
- | `resetOnDepsChange` | `false` | 依赖变化时,如果 `useDictionary` 收到目标字段路径,调用 `form.setFieldValue(fieldName, undefined)` |
404
- | `retryCount` | `0` | 失败后的额外重试次数;总尝试次数为 `retryCount + 1` |
405
- | `retryInterval` | `1000` | 两次尝试之间等待的毫秒数 |
406
- | `onError` | 无 | 最终失败后接收规范化的 `Error` 和表单实例 |
407
- | `onSuccess` | 无 | `formatter` 完成、`list` 写入后接收最终数组和表单实例 |
408
- | `onDepsChange` | 无 | 依赖变化后、`shouldFetch` 判断前调用 |
501
+ | 字段 | 默认值 | 真实行为 |
502
+ | ------------------- | ------------------- | -------------------------------------------------------------------------------------------------------- |
503
+ | `api` | 必填 | 接收加载开始时的完整表单快照和实例;声明第三个参数时还会收到当前请求的 `AbortSignal`;支持同步或异步返回 |
504
+ | `formatter` | 直接使用 `api` 结果 | 在请求成功后转换结果;支持异步,返回值应为选项数组 |
505
+ | `dependsOn` | `undefined` | 通过 `useWatchFields` 监听这些字段;变化时执行依赖回调、可选重置和重新加载 |
506
+ | `shouldFetch` | 总是加载 | 每次加载前判断;返回 `false` 时跳过 `api`、清空 `list` 并结束加载状态 |
507
+ | `immediate` | `true` | 组件 `onMounted` 时是否自动调用一次 `loadDict()`;不影响依赖变化或手动刷新 |
508
+ | `resetOnDepsChange` | `false` | 依赖变化时,如果 `useDictionary` 收到目标字段路径,调用 `form.setFieldValue(fieldName, undefined)` |
509
+ | `retryCount` | `0` | 失败后的额外重试次数;总尝试次数为 `retryCount + 1` |
510
+ | `retryInterval` | `1000` | 两次尝试之间等待的毫秒数 |
511
+ | `onError` | 无 | 最终失败后接收规范化的 `Error` 和表单实例 |
512
+ | `onSuccess` | 无 | `formatter` 完成、`list` 写入后接收最终数组和表单实例 |
513
+ | `onDepsChange` | 无 | 依赖变化后、`shouldFetch` 判断前调用 |
409
514
 
410
515
  当前类型没有 `data`、`list` 或 `options` 形式的静态数组字段。同步 `api` 可以表达静态来源:
411
516
 
412
517
  ```ts
413
- const staticDictionary: SchemxDictionary<ProfileValues, Option[]> = {
518
+ const staticDictionary: SchemxDictionary<ProfileValues, Option[], Option> = {
414
519
  api: () => [
415
520
  { label: "公开", value: "public" },
416
521
  { label: "私密", value: "private" },
@@ -425,7 +530,11 @@ type CityResponse = {
425
530
  data: Array<{ id: number; name: string }>
426
531
  }
427
532
 
428
- const cityDictionary: SchemxDictionary<ProfileValues, CityResponse> = {
533
+ const cityDictionary: SchemxDictionary<
534
+ ProfileValues,
535
+ CityResponse,
536
+ { label: string; value: number }
537
+ > = {
429
538
  api: async () => {
430
539
  const response = await fetch("/api/cities")
431
540
  return (await response.json()) as CityResponse
@@ -448,7 +557,8 @@ type AddressValues = {
448
557
 
449
558
  const cityDictionary: SchemxDictionary<
450
559
  AddressValues,
451
- Array<{ id: string; name: string }>
560
+ Array<{ id: string; name: string }>,
561
+ { label: string; value: string }
452
562
  > = {
453
563
  api: (values) => fetchCities(values.province!),
454
564
  formatter: (cities) => cities.map((city) => ({ label: city.name, value: city.id })),
@@ -465,48 +575,53 @@ const cityDictionary: SchemxDictionary<
465
575
  function useDictionary<
466
576
  TValues extends Values = Values,
467
577
  TName extends NamePath<TValues> = NamePath<TValues>,
468
- >(options: SchemxDictionary<TValues>, fieldName?: TName): UseDictionaryReturn
578
+ TResponse = unknown,
579
+ TOption = unknown,
580
+ >(
581
+ options: SchemxDictionary<TValues, TResponse, TOption>,
582
+ fieldName?: TName
583
+ ): UseDictionaryReturn<TOption>
469
584
  ```
470
585
 
471
586
  `useDictionary` 必须在已经提供表单上下文的后代组件 `setup()` 中同步调用,例如 `Schemx` 的后代 Renderer。`fieldName` 只供 `resetOnDepsChange` 清空目标字段使用。通过 `WithRemoteOptions` 包装、且位于 `Field` 内的 Renderer 会自动从字段 Context 取得当前字段路径;直接调用 `useDictionary()` 或脱离 `Field` 使用 HOC 时,仍可显式传入该参数。
472
587
 
473
588
  `UseDictionaryReturn` 的全部成员如下:
474
589
 
475
- | 成员 | 类型 | 说明 |
476
- | ---------- | ------------------------- | ---------------------------------------------------------------- |
477
- | `list` | `Ref<any[]>` | 最终选项数组;初始值为 `[]` |
478
- | `loading` | `Ref<boolean>` | 通过 `shouldFetch` 后开始请求时为 `true`,成功或失败后为 `false` |
479
- | `error` | `Ref<Error \| undefined>` | 新请求开始时清空;最终失败时写入规范化的 `Error` |
480
- | `loadDict` | `() => Promise<void>` | 使用当前配置和当前表单值执行加载 |
481
- | `refresh` | `() => Promise<void>` | `loadDict` 的同语义包装;不会绕过 `shouldFetch` |
482
- | `mutate` | `(data: any[]) => void` | 直接替换 `list`,不调用 `api`,也不修改 `loading` / `error` |
590
+ | 成员 | 类型 | 说明 |
591
+ | ---------- | --------------------------- | ---------------------------------------------------------------- |
592
+ | `list` | `Ref<TOption[]>` | 最终选项数组;初始值为 `[]` |
593
+ | `loading` | `Ref<boolean>` | 通过 `shouldFetch` 后开始请求时为 `true`,成功或失败后为 `false` |
594
+ | `error` | `Ref<Error \| undefined>` | 新请求开始时清空;最终失败时写入规范化的 `Error` |
595
+ | `loadDict` | `() => Promise<void>` | 使用当前配置和当前表单值执行加载 |
596
+ | `refresh` | `() => Promise<void>` | `loadDict` 的同语义包装;不会绕过 `shouldFetch` |
597
+ | `mutate` | `(data: TOption[]) => void` | 直接替换 `list`,不调用 `api`,也不修改 `loading` / `error` |
483
598
 
484
599
  成功路径为 `api`(含重试)→ `formatter` → 写入 `list` → `onSuccess`。`shouldFetch`、`api`、`formatter` 或 `onSuccess` 抛错时都会进入 `loadDict()` 的错误路径:抛出值经 `normalizeError` 转为 `Error`,然后写入 `error`、清空 `list`、结束 `loading` 并调用 `onError`。通常这些错误会被处理,`loadDict()` resolve;但 `onError` 本身若抛错,该异常位于 `catch` 块内,没有第二层捕获,`loadDict()` / `refresh()` 返回的 Promise 会 reject。
485
600
 
486
601
  依赖监听中的 `onDepsChange` 在调用 `loadDict()` 之前执行,不在其 `try...catch` 内。`onDepsChange` 自身抛错时会直接从 Watch 回调抛出,并阻止本轮重置字段及重新加载;它不会更新 `useDictionary.error`,也不会调用 `onError`。
487
602
 
488
- 并发加载使用递增计数避免过期的成功响应或异步 `formatter` 结果写入,但不会创建 `AbortController`,底层请求仍会继续执行,`api` 也不会收到 `AbortSignal`。当前错误分支没有过期请求检查;较早请求的迟到错误仍可能覆盖较新结果。另一个边界是:`shouldFetch` 返回 `false` 时不会递增请求计数,已经在途的旧请求仍可能随后写回。需要严格取消语义时,请在业务 `api` 外层管理请求,并避免把 Dictionary 的竞态控制等同于网络中止。
603
+ 每次 `loadDict()` 都会递增请求计数并中止上一次仍在进行的请求。`api` 声明第三个参数时会收到当前请求的 `AbortSignal`;重试等待也可被中止。过期请求的成功结果、异步 `formatter` 结果和错误都不会写入当前状态;`shouldFetch` 返回 `false` 时会清空 `list` 并结束 `loading`。底层 API 是否真正停止仍取决于它是否使用 `AbortSignal`,不要把请求中止等同于业务服务端已经取消处理。
489
604
 
490
605
  ## 自定义 Renderer
491
606
 
492
607
  Renderer 是从 Registry 取出的普通 Vue 组件。`Field` 先展开 `schema.componentProps`,再注入或覆盖以下 Props:
493
608
 
494
- | Prop / listener | 实际值与行为 |
495
- | ----------------------- | ------------------------------------------------------------------------------------------- |
496
- | `value` | 当前字段值 |
497
- | `onUpdate:value(value)` | 直接调用 `field.setValue(value)`;不在这里触发字段级校验 |
498
- | `onChange(value)` | 写入字段值,调用 `schema.componentProps.onChange(value)`,并按 `validationTrigger` 执行校验 |
499
- | `onBlur()` | 不写值,按 `validationTrigger` 执行校验 |
500
- | `readonly` | 当前 ViewSchema 已解析的只读状态,覆盖 `componentProps.readonly` |
501
- | `disabled` | 当前 ViewSchema 已解析的禁用状态,覆盖 `componentProps.disabled` |
502
- | `placeholder` | 当前 ViewSchema 的占位文本,覆盖 `componentProps.placeholder` |
503
- | `formItemProps` | 当前完整 ViewSchema,覆盖 `componentProps.formItemProps` |
609
+ | Prop / listener | 实际值与行为 |
610
+ | ----------------------- | --------------------------------------------------------------------------------------------------------------------- |
611
+ | `value` | 当前字段值 |
612
+ | `onUpdate:value(value)` | 直接调用 `field.setValue(value)`;不在这里触发字段级校验 |
613
+ | `onChange(value)` | 写入字段值,调用 `componentProps.onChange(value)` 和 Schema 顶层 `onChange(value)`,并按 `validationTrigger` 执行校验 |
614
+ | `onBlur()` | 不写值,调用 `componentProps.onBlur(value)` 和 Schema 顶层 `onBlur(form)`,并按 `validationTrigger` 执行校验 |
615
+ | `readonly` | 当前 ViewSchema 已解析的只读状态,覆盖 `componentProps.readonly` |
616
+ | `disabled` | 当前 ViewSchema 已解析的禁用状态,覆盖 `componentProps.disabled` |
617
+ | `placeholder` | 当前 ViewSchema 的占位文本,覆盖 `componentProps.placeholder` |
618
+ | `formItemProps` | 当前完整 ViewSchema,覆盖 `componentProps.formItemProps` |
504
619
 
505
- 其他 `componentProps`(例如 `options`、`readonlyPlaceholder`、`align` 和已经通过声明合并注册的组件专属 Props)原样透传。虽然 core 的 `SchemxBaseComponentProps` 声明了 `formInstance`,当前 Vue `Field` 不会自动注入它。
620
+ 其他 `componentProps`(例如 `options`、`readonlyPlaceholder` 和已经通过声明合并注册的组件专属 Props)原样透传。Vue `Field` 会自动注入当前 Core Form 实例到 `formInstance`,并用完整 ViewSchema 覆盖 `formItemProps`。
506
621
 
507
622
  当前也不会向普通 Renderer 自动注入 `fieldName`、字段校验 `error` / `errors` 或 `loading`。Renderer 如需当前字段路径或响应式状态,可调用 `useFieldContext()`;`WithRemoteOptions` 会自动使用该 Context 的字段路径处理 `resetOnDepsChange`,但不会把内部路径透传给被包装 Renderer。详见下一节。
508
623
 
509
- 注意:`componentProps.onChange`、`componentProps.onBlur` 会分别在框架注入的同名回调中调用。Schema 顶层的 `onChange`、`onBlur` 仍没有在 Vue `Field` 中接线;需要使用回调时应放在 `componentProps` 内。
624
+ 注意:`componentProps.onChange`、`componentProps.onBlur` Schema 顶层的 `onChange`、`onBlur` 都会在 Vue `Field` 的对应回调中调用。若只希望自定义 Renderer 行为,可把回调放在 `componentProps` 内;Schema 顶层回调分别收到字段值和表单实例。
510
625
 
511
626
  ```vue
512
627
  <script setup lang="ts">
@@ -603,9 +718,9 @@ type SchemxWithDictionary<A, T extends Values = Values> = A & {
603
718
  `WithRemoteOptions(WrappedComponent)` 返回一个增强组件。增强组件声明并消费:
604
719
 
605
720
  - `dict?: SchemxDictionary | SchemxDictionary["api"]`:存在时规范化后调用 `useDictionary(dict, fieldName)`。
606
- - `fieldName?: NamePath`:仅作为兼容回退。HOC 位于 `Field` 内时,默认从 `useFieldContext().name` 自动取得当前字段路径;显式值只用于脱离 `Field` 的独立使用,且不会继续传给被包装组件。
721
+ - `fieldName?: NamePath`:仅作为兼容回退。HOC 位于 `Field` 内时,默认从 `useFieldContext().name` 自动取得当前字段路径;显式值只用于脱离 `Field` 的独立使用。当前实现会把该未声明属性随 attrs 一并传给被包装组件。
607
722
 
608
- 被包装组件实际收到所有其余 attrs、原始 `dict`,以及 HOC 决定的 `options` 和 `loading`:
723
+ 被包装组件实际收到所有其余 attrs、规范化后的 `dict`,以及 HOC 决定的 `options` 和 `loading`;函数简写会在这里转换为 `{ api }` 对象:
609
724
 
610
725
  - 有 `dict` 时,Dictionary 的 `list` 和 `loading` 无条件覆盖 attrs 中的静态 `options`、`loading`,即使列表仍为空。
611
726
  - 没有 `dict` 时,原 attrs 的 `options`、`loading` 原样保留。
@@ -720,26 +835,30 @@ componentProps: {
720
835
 
721
836
  ## Composition API
722
837
 
723
- | API | 说明 |
724
- | --------------------------- | ------------------------------------------------------------------------------------------------------ |
725
- | `useForm()` | 创建由当前 Vue effect scope 管理生命周期的表单实例;自动使用 Vue 包全局 Registry,但不会自动 `provide` |
726
- | `createFormContext()` | 在当前组件 `setup()` 同步阶段向后代提供表单实例;不接管实例所有权 |
727
- | `useFormContext()` | 获取最近祖先提供的表单实例;缺少上下文时抛错 |
728
- | `useField()` | 创建字段级读写、校验和状态控制器 |
729
- | `createFieldContext()` | 向后代提供字段控制器 |
730
- | `useFieldContext()` | 获取当前字段控制器 |
731
- | `createFormConfigContext()` | 向后代提供表单展示配置 |
732
- | `useFormConfigContext()` | 获取上层表单展示配置 |
733
- | `useWatch()` | 按单字段、多字段或全表签名监听变化 |
734
- | `useWatchField()` | 监听单个字段 |
735
- | `useWatchFields()` | 监听多个字段 |
736
- | `useWatchAll()` | 监听整张表单 |
737
- | `useDictionary()` | 管理依赖字段的函数式选项来源 |
738
- | `useStableRef()` | 创建引用保持稳定的 `shallowRef` |
739
- | `useViewSchemas()` | 把 `subscribeViewSchemas()` 桥接为 Vue `shallowRef` |
740
- | `useFormSelector()` | 从共享表单值 Runtime 派生只读 Vue Ref |
741
-
742
- `useForm()` 只负责创建和销毁实例。如需让自定义组件树中的 `useField()`、`useDictionary()` `Field` 找到实例,Provider 必须在 `setup()` 的同步调用栈中调用 `createFormContext(form)`;展示层还应调用 `createFormConfigContext({ schemaConfig })`。直接使用 `<Schemx>` 时,这两种上下文已经由组件提供。
838
+ | API | 说明 |
839
+ | ------------------------------- | ------------------------------------------------------------------------------------------------------ |
840
+ | `useForm()` | 创建由当前 Vue effect scope 管理生命周期的表单实例;自动使用 Vue 包全局 Registry,但不会自动 `provide` |
841
+ | `provideFormContext()` | 在当前组件 `setup()` 同步阶段一次向后代提供表单实例和展示配置 |
842
+ | `createFormContext()` | 兼容 API:仅提供表单实例;建议改用 `provideFormContext()` |
843
+ | `useFormContext()` | 获取最近祖先提供的表单实例;缺少上下文时抛错 |
844
+ | `useField()` | 创建字段级读写、校验和状态控制器 |
845
+ | `createFieldContext()` | 向后代提供字段控制器 |
846
+ | `useFieldContext()` | 获取当前字段控制器 |
847
+ | `createFormConfigContext()` | 兼容 API:仅提供表单展示配置;建议改用 `provideFormContext()` |
848
+ | `useFormConfigContext()` | 获取上层表单展示配置 |
849
+ | `createConfigProviderContext()` | 创建组件树级 ConfigProvider 上下文;通常由 `<ConfigProvider>` 内部调用。 |
850
+ | `useConfigProviderContext()` | 获取当前 ConfigProvider 配置;没有 Provider 时返回 `undefined`。 |
851
+ | `useConfigProviderContextRef()` | 获取当前 ConfigProvider 的响应式配置引用;没有 Provider 时返回 `undefined`。 |
852
+ | `useWatch()` | 按单字段、多字段或全表签名监听变化 |
853
+ | `useWatchField()` | 监听单个字段 |
854
+ | `useWatchFields()` | 监听多个字段 |
855
+ | `useWatchAll()` | 监听整张表单 |
856
+ | `useDictionary()` | 管理依赖字段的函数式选项来源 |
857
+ | `useStableRef()` | 创建引用保持稳定的 `shallowRef` |
858
+ | `useViewSchemas()` | 把 `subscribeViewSchemas()` 桥接为 Vue `shallowRef` |
859
+ | `useFormSelector()` | 从共享表单值 Runtime 派生只读 Vue Ref |
860
+
861
+ `useForm()` 只负责创建和销毁实例。如需让自定义组件树中的 `useField()`、`useDictionary()` 或 `Field` 找到实例,应在 `setup()` 的同步调用栈中调用 `provideFormContext({ form, schemaConfig })`,一次提供表单实例和展示配置。`createFormContext()` 与 `createFormConfigContext()` 仍保留用于兼容旧代码。直接使用 `<Schemx>` 时,统一 Form Context 已由组件提供。
743
862
 
744
863
  ### 通用调用规则
745
864
 
@@ -750,22 +869,25 @@ componentProps: {
750
869
  ```ts
751
870
  function useForm<TValues extends Values = Values>(
752
871
  options?: CreateFormOptions<TValues, NamePath<TValues>>
753
- ): VueSchemxInstance<TValues>
872
+ ): SchemxInstance<TValues>
754
873
  ```
755
874
 
756
- 源码中参数类型名为 `UseFormOptions<TValues>`,结构等同上面的 `CreateFormOptions`;`UseFormOptions` 未从根入口导出。`options` 可选,未传 Registry 时使用 Vue 全局 `rendererRegistry` 和 `presetRuleRegistry`。函数同步返回 `VueSchemxInstance<TValues>`:它与 `SchemxInstance<TValues>` 结构兼容,但 `getFieldValue()`、`getFieldErrors()`、`isFieldTouched()`、`isFieldPending()`、`getFieldsValue()` 和聚合状态读取可被 Vue effect 追踪。`useForm()` 不读取 Context,也**不会自动 `provide`**;当前 Vue effect scope 销毁时会释放 Runtime 并销毁 Form。非 Vue scope 场景应改用 Core `createForm()` 并自行销毁。
875
+ `options` 可选,未传 Registry 时使用 Vue 全局 `rendererRegistry` 和 `presetRuleRegistry`。函数同步返回 `SchemxInstance<TValues>`,其中 `getFieldValue()`、`getFieldErrors()`、`isFieldTouched()`、`isFieldPending()`、`getFieldsValue()` 和聚合状态读取可被 Vue effect 追踪。`useForm()` 不读取 Context,也**不会自动 `provide`**;当前 Vue effect scope 销毁时会释放 Runtime 并销毁 Form。非 Vue scope 场景应改用 Core `createForm()` 并自行销毁。
757
876
 
758
877
  ```ts
759
- import { createFormContext, useForm } from "@schemx/vue"
878
+ import { provideFormContext, useForm } from "@schemx/vue"
760
879
 
761
880
  type ProfileValues = { nickname: string }
762
881
  const form = useForm<ProfileValues>({ initialValues: { nickname: "" } })
763
882
 
764
- // 需要让后代 Hook 读取时,必须显式提供。
765
- createFormContext(form)
883
+ // 需要让后代 Hook 读取时,同时提供表单实例和展示配置。
884
+ provideFormContext({
885
+ form,
886
+ schemaConfig: { readonly: false, validationTrigger: "blur" },
887
+ })
766
888
  ```
767
889
 
768
- `useForm()` 除了补全 Vue 全局 Registry 外,会把 Core options 原样传给 `createForm()`。因此直接调用时,`initialValues` 会按 Core 规则形成初始快照,`submit()` 也会等待直接传入的 `onFinish` Promise。前文 `modelValue` 的初始化与同步行为,以及 `onFinish` Promise 不被等待的限制,只属于 `<Schemx>` 内部创建实例时的 Props 转换与回调包装,不属于 `useForm()` 本身。`defaultRendererType` 仍会受全局 Renderer Registry 已被补全的影响,见前文说明。
890
+ `useForm()` 除了补全 Vue 全局 Registry 外,会把 Core options 原样传给 `createForm()`。因此直接调用时,`initialValues` 会按 Core 规则形成初始快照,`submit()` 也会等待直接传入的 `onFinish` Promise。前文 `modelValue` 的初始化与同步行为只属于 `<Schemx>` 内部创建实例时的 Props 转换,不属于 `useForm()` 本身。`defaultRendererType` 仍会受全局 Renderer Registry 已被补全的影响,见前文说明。
769
891
 
770
892
  ### Vue Instance 与共享 Runtime
771
893
 
@@ -773,68 +895,68 @@ createFormContext(form)
773
895
 
774
896
  `useFormSelector()` 和 `useField()` 复用这个 Runtime;前者返回 selector 结果的只读 Ref,后者复用字段 `value`、`errors`、`touched` 和 `pending` Ref。Runtime 通过 `@schemx/core/adapter` 的 `createFormStateAdapter()` 消费 Core `SnapshotSource`。最后一个 Vue owner 释放或手动调用 `form.destroy()` 后,Runtime 会停止订阅并释放这些快照来源。
775
897
 
776
- ### 3 组 Context API
898
+ ### Context API
777
899
 
778
- 3 组 Reader 都要求 Context 存在,没有可选读取模式或默认值。`create*Context()` 必须在 Provider 组件的 `setup()` 同步阶段调用,且只对后代可见;`use*Context()` 仅读取最近祖先提供的值。
900
+ Form、Field 和 ConfigProvider 是 3 组 Context。Form 与 Field 的 Reader 要求对应 Context 存在;ConfigProvider Reader 在没有 Provider 时返回 `undefined`。`provideFormContext()` 和 `create*Context()` 必须在 Provider 组件的 `setup()` 同步阶段调用,且只对后代可见;`use*Context()` 仅读取最近祖先提供的值。
779
901
 
780
902
  ```ts
903
+ function provideFormContext<TValues extends Values = Values>(
904
+ context: FormContextValue<TValues>
905
+ ): SchemxInstance<TValues>
906
+ function useFormContextValue<TValues extends Values = Values>(): FormContextValue<TValues>
907
+ function useFormContext<TValues extends Values = Values>(): SchemxInstance<TValues>
908
+
781
909
  function createFormContext<TValues extends Values = Values>(
782
910
  instance: SchemxInstance<TValues>
783
- ): VueSchemxInstance<TValues>
784
- function useFormContext<TValues extends Values = Values>(): VueSchemxInstance<TValues>
911
+ ): SchemxInstance<TValues>
785
912
 
786
913
  function createFieldContext<TValues extends Values = Values>(
787
914
  field: FieldInstance<TValues>
788
915
  ): void
789
916
  function useFieldContext(): FieldInstance<Values>
790
917
 
791
- function createFormConfigContext<TValues extends Values = Values>(
792
- props: FormContextProps
793
- ): void
794
- function useFormConfigContext(): FormContextProps
918
+ function createFormConfigContext(props: FormConfigContextValue): void
919
+ function useFormConfigContext(): FormConfigContextValue
920
+
921
+ function createConfigProviderContext(config: ComputedRef<SchemxConfig>): void
922
+ function useConfigProviderContext(): SchemxConfig | undefined
923
+ function useConfigProviderContextRef(): ComputedRef<SchemxConfig> | undefined
795
924
  ```
796
925
 
797
926
  上面签名中的 `FieldInstance` 已从 `@schemx/vue` 根入口导出。`createFieldContext()` 当前只有 `TValues extends Values = Values`,**没有独立的 `TName` 泛型**;`field` 必须是 `useField()` 返回的 Vue 字段控制器,字段路径已由创建该返回值时的 `name` 捕获。调用方可以显式导入 `FieldInstance`,也可以依靠 `useField()` 推导参数。
798
927
 
799
- | Provider 签名 | Reader 签名 | 职责、所有权与缺失行为 |
800
- | --------------------------------------------------------------------- | ------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- |
801
- | `createFormContext<T>(form: SchemxInstance<T>): VueSchemxInstance<T>` | `useFormContext<T>(): VueSchemxInstance<T>` | 将 Core Form 或已有 Instance 归一化后提供 / 读取。Provider 只持有 Runtime,不销毁外部 Core Form;缺失时 Reader 抛出带 `createFormContext(form)` 指引的 `Error`。 |
802
- | `createFieldContext<TValues extends Values = Values>(field): void` | `useFieldContext(): FieldInstance<Values>` | 提供 / 读取 `useField()` 返回的字段控制器。Provider 不创建字段、不接管订阅;缺失时 Reader 抛出指向 `createFieldContext(field)` 的 `Error`。 |
803
- | `createFormConfigContext<T>(props: FormContextProps<T>): void` | `useFormConfigContext(): FormContextProps` | 提供 / 读取表单展示配置。Provider 不复制、不更新传入对象;缺失时 Reader 抛出带 `createFormConfigContext(props)` 指引的 `Error`。 |
928
+ | Provider 签名 | Reader 签名 | 职责、所有权与缺失行为 |
929
+ | ------------------------------------------------------------------ | ----------------------------------------------- | -------------------------------------------------------------------------------------------------------- |
930
+ | `provideFormContext<T>({ form, schemaConfig })` | `useFormContextValue<T>(): FormContextValue<T>` | 一次提供响应式表单实例和展示配置;Provider 只持有 Runtime,不销毁外部 Core Form|
931
+ | `provideFormContext<T>({ form, schemaConfig })` | `useFormContext<T>(): SchemxInstance<T>` | 只读取统一 Context 中的表单实例;缺失时 Reader 抛出 `Error`。 |
932
+ | `createFormContext<T>(form)`(兼容) | `useFormContext<T>(): SchemxInstance<T>` | 仅提供表单实例的旧 API;建议迁移到 `provideFormContext()`。 |
933
+ | `createFieldContext<TValues extends Values = Values>(field): void` | `useFieldContext(): FieldInstance<Values>` | 提供 / 读取 `useField()` 返回的字段控制器。Provider 不创建字段、不接管订阅;缺失时 Reader 抛出 `Error`。 |
934
+ | `createFormConfigContext(props)`(兼容) | `useFormConfigContext(): FormConfigContextValue` | 仅提供 / 读取表单展示配置的旧 API;建议迁移到 `provideFormContext()`。 |
804
935
 
805
936
  ```ts
806
- import {
807
- createFormConfigContext,
808
- createFormContext,
809
- useForm,
810
- type FormContextProps,
811
- type SchemxField,
812
- } from "@schemx/vue"
937
+ import { provideFormContext, useForm, type SchemxField } from "@schemx/vue"
813
938
 
814
939
  type ProfileValues = { nickname: string }
815
940
  const schemas: SchemxField<ProfileValues>[] = [
816
941
  { name: "nickname", label: "昵称", componentType: "input" },
817
942
  ]
818
943
  const form = useForm<ProfileValues>({ schemas })
819
- const config: FormContextProps<ProfileValues> = {
944
+ provideFormContext({
945
+ form,
820
946
  schemaConfig: {
821
947
  readonly: false,
822
948
  validationTrigger: "blur",
823
949
  },
824
- }
825
-
826
- createFormContext(form)
827
- createFormConfigContext(config)
950
+ })
828
951
  ```
829
952
 
830
953
  在后代组件的 `setup()` 中只读取所需 Context:
831
954
 
832
955
  ```ts
833
- import { useFieldContext, useFormConfigContext, useFormContext } from "@schemx/vue"
956
+ import { useFieldContext, useFormContextValue } from "@schemx/vue"
834
957
 
835
958
  type ProfileValues = { nickname: string }
836
- const form = useFormContext<ProfileValues>()
837
- const formConfig = useFormConfigContext()
959
+ const { form, schemaConfig } = useFormContextValue<ProfileValues>()
838
960
  const field = useFieldContext()
839
961
  ```
840
962
 
@@ -863,9 +985,9 @@ console.log(nickname.value.value, nickname.errors.value)
863
985
 
864
986
  `createFieldContext(field)` 将这一返回值提供给后代并返回 `void`;`useFieldContext()` 无参数,返回最近祖先提供的同一控制器。它们不会替代表单 Context。
865
987
 
866
- ### `FormContextProps` 的当前边界
988
+ ### `FormContextValue` 与 `FormConfigContextValue` 的边界
867
989
 
868
- `FormContextProps<T>` 只包含嵌套的 `schemaConfig`,不包含 `schemas`、`initialValues`、`form`、回调、`class`、`style`、Registry 或 `defaultRendererType`。组件 Props 中的平铺 Schema 字段会在 `<Schemx>` 内部聚合为 `schemaConfig`,再分别传给 Form 实例和字段展示 Context。
990
+ `FormContextValue<T>` 同时包含 `form` 和展示配置,`FormConfigContextValue` 只包含展示配置。两者都不包含 `schemas`、`initialValues`、回调、`class`、`style`、Registry 或 `defaultRendererType`。组件 Props 中的平铺 Schema 字段会在 `<Schemx>` 内部聚合为 `schemaConfig`,再传给 Form 实例和字段展示 Context。
869
991
 
870
992
  ### `useWatch`、`useWatchField`、`useWatchFields` 与 `useWatchAll`
871
993
 
@@ -903,31 +1025,34 @@ function useWatchAll<T extends Values = Values>(
903
1025
 
904
1026
  `useWatch` 按参数形状分发,3 个语义化函数分别对应单字段、多字段和全表重载。它们都从 `useFormContext()` 读取表单,返回可手动调用的取消函数,并在组件卸载时自动取消。`options.immediate` 和 `options.inequality` 默认均为 `false`;后者使用深比较跳过相等值。
905
1027
 
906
- | 模式 | callback 第 1 个参数 | callback 第 2 个参数 |
907
- | ------ | ------------------------------------------------------------------------------------------------------- | -------------------- |
908
- | 单字段 | `{ value, prevValue }`;`immediate` 首次的 `prevValue` 为 `undefined`。 | 变化后的全表快照。 |
909
- | 多字段 | `{ changedPaths, changedValues, prevValues }`;`immediate` 时路径为全部传入路径、`prevValues` 为 `{}`。 | 变化后的全表快照。 |
910
- | 全表 | 与多字段相同;`immediate` 时 `changedPaths` 为 `[]`。 | 变化后的全表快照。 |
1028
+ | 模式 | callback 第 1 个参数 | callback 第 2 个参数 |
1029
+ | ------ | -------------------- | ------------------------------------------------------------------------------------------------------- |
1030
+ | 单字段 | 变化后的全表快照。 | `{ value, prevValue }`;`immediate` 首次的 `prevValue` 为 `undefined`。 |
1031
+ | 多字段 | 变化后的全表快照。 | `{ changedPaths, changedValues, prevValues }`;`immediate` 时路径为全部传入路径、`prevValues` 为 `{}`。 |
1032
+ | 全表 | 变化后的全表快照。 | `{ changedPaths, changedValues, prevValues }`;`immediate` 时 `changedPaths` 为 `[]`。 |
911
1033
 
912
- 当前 Core 全表实现在 effect 中读取无追踪的 `getFieldsSnapshot()`,因此 `useWatchAll()` 与 `useWatch(callback)` 通常不会在后续字段变化时再执行;`immediate: true` 仍会同步执行 1 次。需要持续监听时应使用 `useWatchField()` 或 `useWatchFields()`。
1034
+ `useWatchAll()` 与 `useWatch(callback)` 会在 effect 中读取可追踪的全表值,因此会在字段变化时执行;`immediate: true` 还会在创建监听时同步执行 1 次。需要减少监听范围时可使用 `useWatchField()` 或 `useWatchFields()`。
913
1035
 
914
1036
  ```ts
915
1037
  import { useWatch, useWatchAll, useWatchField, useWatchFields } from "@schemx/vue"
916
1038
 
917
1039
  type ProfileValues = { firstName: string; lastName: string }
918
- useWatch<ProfileValues>("firstName", ({ value, prevValue }) => {
1040
+ useWatch<ProfileValues>("firstName", (_snapshot, { value, prevValue }) => {
919
1041
  console.log(prevValue, value)
920
1042
  })
921
1043
  useWatchField<ProfileValues>(
922
1044
  "firstName",
923
- ({ value, prevValue }, snapshot) => console.log(prevValue, value, snapshot),
1045
+ (snapshot, { value, prevValue }) => console.log(prevValue, value, snapshot),
924
1046
  { immediate: true, inequality: true }
925
1047
  )
926
- const stop = useWatchFields<ProfileValues>(["firstName", "lastName"], (payload) => {
927
- console.log(payload.changedPaths, payload.changedValues)
928
- })
1048
+ const stop = useWatchFields<ProfileValues>(
1049
+ ["firstName", "lastName"],
1050
+ (_snapshot, payload) => {
1051
+ console.log(payload.changedPaths, payload.changedValues)
1052
+ }
1053
+ )
929
1054
  useWatchAll<ProfileValues>(
930
- (payload, snapshot) => {
1055
+ (snapshot, payload) => {
931
1056
  console.log(payload.changedPaths, snapshot)
932
1057
  },
933
1058
  { immediate: true }
@@ -937,7 +1062,7 @@ stop()
937
1062
 
938
1063
  ### `useDictionary` 摘要
939
1064
 
940
- 签名为 `useDictionary<TValues, TName>(options, fieldName?): UseDictionaryReturn`。它通过 `useFormContext()` 取得表单,在 `onMounted` 时按 `immediate` 决定是否加载,并通过 `useWatchFields()` 自动清理依赖订阅。完整参数、返回值、竞态边界与示例见前文 [`useDictionary`](#usedictionary),这里不重复维护第 2 份定义。
1065
+ 签名为 `useDictionary<TValues, TName, TResponse, TOption>(options, fieldName?): UseDictionaryReturn<TOption>`。它通过 `useFormContext()` 取得表单,在 `onMounted` 时按 `immediate` 决定是否加载,并通过 `useWatchFields()` 自动清理依赖订阅。完整参数、返回值、竞态边界与示例见前文 [`useDictionary`](#usedictionary),这里不重复维护第 2 份定义。
941
1066
 
942
1067
  ### `useStableRef`
943
1068
 
@@ -981,42 +1106,48 @@ console.log(viewSchemas.value)
981
1106
 
982
1107
  ### `Field`
983
1108
 
984
- `Field` 只接受一个必填 Prop
1109
+ `Field` 的必填 Prop 是 `schema`,还支持用于包装器的 `class` 和 `style`:
985
1110
 
986
1111
  | Prop | 类型 | 说明 |
987
1112
  | -------- | -------------------------- | ----------------------------------------------------------- |
988
- | `schema` | `SchemxViewFieldSchema<T>` | core 已解析完成的字段 ViewSchema,不是原始 `SchemxField<T>` |
1113
+ | `schema` | `SchemxViewFieldSchema<T>` | Core 已解析完成的字段 ViewSchema,不是原始 `SchemxField<T>` |
1114
+ | `class` | `ClassValue` | 追加到字段外层 wrapper 的 class。 |
1115
+ | `style` | `StyleValue` | 追加到字段外层 wrapper 的内联 style。 |
989
1116
 
990
1117
  `Field` 只处理普通字段 ViewSchema:它创建字段控制器、提供字段上下文、查找 Renderer,并处理标签、内容、错误、校验触发和可见性。`Schemx` 会在根级 ViewSchema 循环中直接区分并渲染 `Field` 或 `Group`。
991
1118
 
992
1119
  它支持与 `Schemx` 一致的动态 Slots:`{name}`、`{name}Label`、`{name}Before`、`{name}Content`、`{name}After`、`{name}Error` 和 `{name}:{slotName}`。完整 Slot Props 见 [Schemx 组件的 Slots](#slots)。
993
1120
 
994
- `Field` 不能脱离上下文单独工作:普通字段至少需要祖先同步提供 `SchemxInstance` 和 `FormContextProps`,通常直接放在 `<Schemx>` 内部。若自定义 adapter 直接使用它,需要同时调用 `createFormContext(form)` `createFormConfigContext(config)`。传给它的 Schema 应来自 `form.getViewSchemas()` 或 `useViewSchemas(form)`,不要把尚未编译的 dependency Schema 直接传入。
1121
+ `Field` 不能脱离上下文单独工作:普通字段至少需要祖先同步提供表单实例和展示配置,通常直接放在 `<Schemx>` 内部。若自定义 adapter 直接使用它,应调用 `provideFormContext({ form, schemaConfig })`。传给它的 Schema 应来自 `form.getViewSchemas()` 或 `useViewSchemas(form)`,不要把尚未编译的 dependency Schema 直接传入。
995
1122
 
996
1123
  ### `Group`
997
1124
 
998
- `Group` 同样只有一个必填 Prop
1125
+ `Group` 的必填 Prop 是 `schema`,还支持外层样式和递归渲染回调:
999
1126
 
1000
- | Prop | 类型 | 说明 |
1001
- | -------- | -------------------------- | --------------------------------------- |
1002
- | `schema` | `SchemxViewGroupSchema<T>` | 包含已解析 `children` 的分组 ViewSchema |
1127
+ | Prop | 类型 | 说明 |
1128
+ | ---------------- | -------------------------- | ----------------------------------------------------------------------------------- |
1129
+ | `schema` | `SchemxViewGroupSchema<T>` | 包含已解析 `children` 的分组 ViewSchema |
1130
+ | `class` | `ClassValue` | 追加到 Group 外层 wrapper 的 class。 |
1131
+ | `style` | `StyleValue` | 追加到 Group 外层 wrapper 的内联 style。 |
1132
+ | `renderChildren` | `(schemas, rowConfig?) => VNodeChild` | 可选;`<Schemx>` 由 SchemaList 提供,直接挂载 Group 时省略则使用兼容递归渲染。 |
1003
1133
 
1004
1134
  它会把收到的全部 Slots 原样传给子级 `Field` 或嵌套 `Group`,并支持 `{groupKey}Header`、`{groupKey}Label`、`{groupKey}Content` 三个分组自身 Slot。`Header` 替换 Header 内部内容,`Label` 替换标题,`Content` 替换 Body 内的默认子字段布局;三者都接收 `schema`、`collapsed`、`collapsible`、`disabled`、`readonly` 和 `toggle`。`collapsible` 控制标题是否可点击和通过 Enter / Space 切换;`disabled` 状态禁止折叠交互,`readonly` 状态仍允许浏览和折叠。组件支持受控与非受控折叠;从受控切换为非受控时会延续最后一次受控值。`destroyOnCollapse` 控制子级是否卸载,ARIA 关联 ID 优先使用 Core Node ID,直接挂载组件时回退到 Vue 实例 ID,避免规范化后相同 key 发生冲突。
1005
1135
 
1006
1136
  `label` 为空时不渲染标题。Vue 源码的 `types/index.ts` 通过声明合并为分组 Schema 增加 `class` 和 `style`,发布声明入口会加载该增强;运行时将二者绑定到 `.schemx-group-wrapper` 外层容器。子级字段仍要求表单实例和展示配置上下文。
1007
1137
 
1008
- `Field` 和 `Group` 是构建自定义 Vue adapter 或重排 ViewSchemas 时的底层组件。一般业务表单优先使用 `<Schemx>`;只有在需要自定义整体布局、分区或容器时才直接组合这两个组件。
1138
+ `Field` 和 `Group` 是构建自定义 Vue adapter 或重排 ViewSchemas 时的底层组件。一般业务表单优先使用 `<Schemx>`;只有在需要自定义整体布局、分区或容器时才直接组合这两个组件。由 `<Schemx>` 渲染时,`SchemaList` 会传入 `renderChildren` 来统一处理子级布局;直接挂载 `Group` 时也可省略该回调,组件会递归渲染子级作为兼容默认行为。需要自定义子级布局时可传入自己的回调。
1009
1139
 
1010
1140
  `class` 和 `style` 支持多来源合并。`Schemx` 根节点使用内部 `schemx` class 与组件 Props;Field 外层容器按“内部 class → 父级传入 class/style → Schema 的 `class`/`style`”合并;Group 外层容器按同样顺序合并。class 会全部保留,style 后面的来源覆盖前面的同名属性。Field Schema 样式作用于 `.schemx-field-wrapper`,Group Schema 样式作用于 `.schemx-group-wrapper`。
1011
1141
 
1012
1142
  ## Registry
1013
1143
 
1014
- Vue 包自有 2 个模块级单例:
1144
+ Vue 包保留 2 个模块级 fallback Registry;通过 `app.use()` 使用适配包时,会为每个 Vue App
1145
+ 创建独立的配置 Registry 和适配包 Scope。
1015
1146
 
1016
- | 导出 | 真实类型 | 初始内容 | 与 `useForm()` 的关系 |
1017
- | -------------------- | ------------------------------------- | ---------------------------------------------------------------------------------- | ------------------------------------------------ |
1018
- | `rendererRegistry` | `RendererRegistry<SchemxRendererKey>` | 空 Registry,默认 renderer key 预设为 `"input"`;未注册 `input` 时仍无法取得组件。 | 未传 `options.rendererRegistry` 时使用该单例。 |
1019
- | `presetRuleRegistry` | `PresetRuleRegistry` | 模块初始化时为空,只保存显式注册的预设规则;`required` 不会写入 Registry。 | 未传 `options.presetRuleRegistry` 时使用该单例。 |
1147
+ | 导出 | 真实类型 | 初始内容 | 与 `useForm()` 的关系 |
1148
+ | -------------------- | -------------------- | -------------------------------------------------------------------------------- | --------------------------------------------------------------- |
1149
+ | `rendererRegistry` | `RendererRegistry` | 空 Registry,默认 renderer key 预设为 `"input"`;适配包直接挂载时使用 fallback。 | 未传 `options.rendererRegistry` 且没有 App Scope 时使用该实例。 |
1150
+ | `presetRuleRegistry` | `PresetRuleRegistry` | 模块初始化时包含内置 `required`,并可继续注册业务预设规则。 | 未传 `options.presetRuleRegistry` 时使用该单例。 |
1020
1151
 
1021
1152
  Renderer Registry 包含 `register`、`registerAll`、`get`、`resolve`、`has`、`unregister`、`keys`、`setFallback`、`getFallback`、`clear` 和 `size`;PresetRuleRegistry 包含 `register`、`registerAll`、`get`、`resolve`、`has`、`unregister`、`keys`、`clear` 和 `size`。完整签名见 Core 的 [校验](../core#校验) 与 [Renderer Registry](../core#renderer-registry) 章节。
1022
1153
 
@@ -1053,21 +1184,37 @@ const validators = createPresetRuleRegistry()
1053
1184
  const form = useForm({ rendererRegistry: renderers, presetRuleRegistry: validators })
1054
1185
  ```
1055
1186
 
1056
- `createRendererRegistry()` 和 `createPresetRuleRegistry()` 是 Core 传递导出,不是 Vue 自有 API。独立 PresetRuleRegistry 创建时为空,只有调用方显式注册的预设规则;必填由字段的 `required` 配置处理。
1187
+ `createRendererRegistry()` 和 `createPresetRuleRegistry()` 是 Core 传递导出,不是 Vue 自有 API。独立 PresetRuleRegistry 创建时包含内置 `required`,也可继续注册调用方的预设规则。
1057
1188
 
1058
1189
  ## 类型参考
1059
1190
 
1060
1191
  Vue 根入口自有以下公开类型:
1061
1192
 
1062
- | 类型 | 定义与用途 |
1063
- | ---------------------------------- | ------------------------------------------------------------------------------------------------------------------- |
1064
- | `FormContextProps` | 表单展示 Context 类型。当前类型与 `<Schemx>` 运行时 omit 的差异见 [Composition API](#formcontextprops-的当前边界)。 |
1065
- | `SchemxDictionary<TValues, R>` | 函数式选项源配置;`R` 从 `api` 传递到 `formatter`。见 [Dictionary](#dictionary) |
1066
- | `SchemxInstallOptions` | 等同于 Core `SchemxConfig`。`app.use(Schemx, options)` 将其保存为当前 Vue App 的默认配置。 |
1067
- | `SchemxWithDictionary<A, TValues>` | `A & { dict?: SchemxDictionary<TValues> }`,只增加可选 `dict`。见 [WithRemoteOptions](#withremoteoptions)。 |
1068
- | `UseDictionaryReturn` | `{ list, loading, error, loadDict, refresh, mutate }`,各成员类型见 [`useDictionary`](#usedictionary)。 |
1069
- | `SchemxFormProps<TValues>` | `Schemx` 组件 Props 类型,由 Core 表单选项和 Vue 专属 `modelValue`、`form`、`class`、`style` 等属性组合而成。 |
1070
- | `FieldInstance<TValues>` | Vue Ref / Computed 桥接后的字段控制器类型,由 `useField()` 返回。 |
1193
+ | 类型 | 定义与用途 |
1194
+ | ----------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------- |
1195
+ | `FormContextValue<TValues>` | Form Context,包含表单实例和展示配置。见 [Composition API](#formcontextvalue-与-formconfigcontextvalue-的边界)。 |
1196
+ | `FormConfigContextValue` | 表单展示配置 Context |
1197
+ | `SchemxDictionary<TValues, TResponse, TOption>` | 函数式选项源配置;`TResponse` `api` 传递到 `formatter`,`TOption` 是格式化后的选项类型。见 [Dictionary](#dictionary)。 |
1198
+ | `SchemxInstallOptions` | 基于 Core `SchemxConfig` App 安装配置;Vue 通过 `SchemxConfigDefinition` 扩展 `row` / `rowComponent` / `colComponent`。 |
1199
+ | `SchemxWithDictionary<A, TValues>` | `A & { dict?: SchemxDictionary<TValues> \| SchemxDictionary<TValues>["api"] }`,只增加可选 `dict`。见 [WithRemoteOptions](#withremoteoptions)。 |
1200
+ | `UseDictionaryReturn<TOption>` | `{ list, loading, error, loadDict, refresh, mutate }`,`list` `mutate` 使用 `TOption`。见 [`useDictionary`](#usedictionary)。 |
1201
+ | `UseDictOptionsReturn<TOption>` | `UseDictionaryReturn<TOption>` 的弃用别名。 |
1202
+ | `SchemxFormProps<TValues>` | `Schemx` 组件 Props 类型,由 Core 表单选项和 Vue 专属 `modelValue`、`form`、`class`、`style` 等属性组合而成。 |
1203
+ | `VueSchemxInstance<TValues>` | `SchemxInstance<TValues>` 的弃用别名。 |
1204
+ | `FieldInstance<TValues>` | Vue Ref / Computed 桥接后的字段控制器类型,由 `useField()` 返回。 |
1205
+ | `SchemxFieldSlotProps<TValues>` | 字段整体、Label、Before、After 插槽的公共参数。 |
1206
+ | `SchemxFieldContentSlotProps<TValues>` | Content 插槽参数,额外包含默认 Renderer 的 `columnElement`。 |
1207
+ | `SchemxFieldErrorSlotProps<TValues>` | Error 插槽参数,额外包含当前字段的 `errors`。 |
1208
+ | `SchemxFieldSlots<TValues>` | `Field` 组件接收的动态字段插槽与 Renderer 子插槽类型。 |
1209
+ | `SchemxFieldSlotValue<TValues>` | 字段区域插槽的参数联合类型。 |
1210
+ | `SchemxGroupSlotProps<TValues>` | Group Header、Label、Content 插槽参数。 |
1211
+ | `SchemxGroupSlots<TValues>` | Group 动态插槽类型映射。 |
1212
+ | `SchemxBaseComponentProps` | Renderer 公共 Props。 |
1213
+ | `SchemxVueBaseComponentProps<TValues>` | `SchemxBaseComponentProps<TValues>` 的弃用别名。 |
1214
+ | `SchemxVueLayout` | `SchemxColConfig` 的弃用别名。 |
1215
+ | `SchemxVueConfig<TValues>` | `SchemxConfig<TValues>` 的弃用别名。 |
1216
+ | `SchemxConfig` | Core 表单配置;Vue 通过 `SchemxConfigDefinition` 扩展布局组件配置。 |
1217
+ | `SchemxFormActionConfig`、`SchemxFormAction` | 内置提交 / 重置按钮配置。 |
1071
1218
 
1072
1219
  除上述类型外,不要从 `@schemx/vue/src/*` 或 `@schemx/vue/dist/*` 深层导入。
1073
1220
 
@@ -1081,172 +1228,210 @@ Vue 根入口自有以下公开类型:
1081
1228
 
1082
1229
  ### Vue 自有导出
1083
1230
 
1084
- | 分类 | 导出 | 用途 |
1085
- | --------------- | ----------------------------------- | --------------------------------------------- |
1086
- | 表单组件 | `schemxForm` | 可安装的表单组件;与 `default` 指向同一对象。 |
1087
- | 组件 | `Field` | 渲染字段 ViewSchema。 |
1088
- | 组件 | `Group` | 渲染分组 ViewSchema。 |
1089
- | HOC | `WithRemoteOptions` | Renderer 接入 Dictionary。 |
1090
- | Registry | `rendererRegistry` | Vue 全局 Renderer Registry。 |
1091
- | Registry | `presetRuleRegistry` | Vue 全局 PresetRuleRegistry。 |
1092
- | Hook | `useForm` | 创建并按 Vue scope 销毁表单。 |
1093
- | Context | `createFormContext` | 提供表单实例。 |
1094
- | Context | `useFormContext` | 读取表单实例。 |
1095
- | Hook | `useField` | 创建 Vue 字段控制器。 |
1096
- | Context | `createFieldContext` | 提供字段控制器。 |
1097
- | Context | `useFieldContext` | 读取字段控制器。 |
1098
- | Context | `createFormConfigContext` | 提供表单展示配置。 |
1099
- | Context | `useFormConfigContext` | 读取表单展示配置。 |
1100
- | Watch | `useWatch` | 统一分发 Vue Watch。 |
1101
- | Watch | `useWatchField` | 单字段 Vue Watch |
1102
- | Watch | `useWatchFields` | 多字段 Vue Watch。 |
1103
- | Watch | `useWatchAll` | 全表 Vue Watch。 |
1104
- | Dictionary | `useDictionary` | 管理函数式选项源。 |
1105
- | Vue 响应式 | `useStableRef` | 建立浅比较稳定 Ref。 |
1106
- | ViewSchema | `useViewSchemas` | 桥接 ViewSchemas 为 Ref。 |
1107
- | Hook | `useFormSelector` | 从表单值派生只读 Vue Ref。 |
1108
- | 默认导出 | `default` | `schemxForm` 严格相等。 |
1109
- | Context 类型 | `FormContextProps` | 表单展示 Context。 |
1110
- | Runtime 类型 | `VueSchemxInstance` | 可在 Vue effect 中追踪读取的 Form Instance。 |
1111
- | Dictionary 类型 | `SchemxDictionary` | 函数式选项源配置。 |
1112
- | 插件类型 | `SchemxInstallOptions` | 当前 Vue App 的默认配置安装选项。 |
1113
- | Dictionary 类型 | `SchemxWithDictionary` | Props 增加 `dict`。 |
1114
- | Dictionary 类型 | `UseDictionaryReturn` | `useDictionary()` 返回值。 |
1115
- | 表单类型 | `SchemxFormProps<TValues>` | `<Schemx>` 组件 Props 类型。 |
1116
- | 字段类型 | `FieldInstance<TValues>` | Vue Ref / Computed 桥接后的字段控制器类型。 |
1117
- | Selector 类型 | `UseFormSelectorOptions<TSelected>` | `useFormSelector` 的比较和刷新配置。 |
1231
+ | 分类 | 导出 | 用途 |
1232
+ | --------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------ |
1233
+ | 表单组件 | `schemxForm` | 可安装的表单组件;与 `default` 指向同一对象。 |
1234
+ | 组件 | `Field` | 渲染字段 ViewSchema。 |
1235
+ | 组件 | `Group` | 渲染分组 ViewSchema。 |
1236
+ | 组件 | `Col` | Field `col` 元数据映射到已注册的 Col 组件。 |
1237
+ | 组件 | `Row` | 将同级 ViewSchema 渲染为已注册的 Row 组件。 |
1238
+ | 组件 | `Icon` | 根据字符串图标名称或 Vue Component 渲染图标。 |
1239
+ | 组件 | `Wrapper` | 提供 Renderer 的只读 / 禁用状态包装。 |
1240
+ | 组件 | `ConfigProvider` | 提供组件树级默认配置。 |
1241
+ | HOC | `WithRemoteOptions` | 为 Renderer 接入 Dictionary。 |
1242
+ | Registry | `rendererRegistry` | Vue 全局 Renderer Registry。 |
1243
+ | Registry | `presetRuleRegistry` | Vue 全局 PresetRuleRegistry。 |
1244
+ | Hook | `useForm` | 创建并按 Vue scope 销毁表单。 |
1245
+ | Context | `provideFormContext` | 一次提供表单实例和展示配置。 |
1246
+ | Context | `useFormContextValue` | 读取统一 Form Context。 |
1247
+ | Context | `useFormContext` | 读取表单实例。 |
1248
+ | Context | `useFormRuntimeContext` | 获取当前表单的共享 Vue Runtime |
1249
+ | Context | `createFormContext` | 兼容 API:仅提供表单实例。 |
1250
+ | Hook | `useField` | 创建 Vue 字段控制器。 |
1251
+ | Context | `createFieldContext` | 提供字段控制器。 |
1252
+ | Context | `useFieldContext` | 读取字段控制器。 |
1253
+ | Context | `createFormConfigContext` | 兼容 API:仅提供表单展示配置。 |
1254
+ | Context | `useFormConfigContext` | 读取兼容表单展示配置。 |
1255
+ | Context | `createConfigProviderContext` | 创建 ConfigProvider 上下文。 |
1256
+ | Context | `useConfigProviderContext` | 读取 ConfigProvider 当前配置。 |
1257
+ | Context | `useConfigProviderContextRef` | 读取 ConfigProvider 响应式配置引用。 |
1258
+ | Watch | `useWatch` | 统一分发 Vue Watch。 |
1259
+ | Watch | `useWatchField` | 单字段 Vue Watch。 |
1260
+ | Watch | `useWatchFields` | 多字段 Vue Watch。 |
1261
+ | Watch | `useWatchAll` | 全表 Vue Watch。 |
1262
+ | Dictionary | `useDictionary` | 管理函数式选项源。 |
1263
+ | Vue 响应式 | `useStableRef` | 建立浅比较稳定 Ref|
1264
+ | ViewSchema | `useViewSchemas` | 桥接 ViewSchemas 为 Ref。 |
1265
+ | Hook | `useFormSelector` | 从表单值派生只读 Vue Ref。 |
1266
+ | 默认导出 | `default` | 与 `schemxForm` 严格相等。 |
1267
+ | Context 类型 | `FormContextValue<TValues>` | 统一 Form Context,包含表单实例和展示配置。 |
1268
+ | Context 类型 | `FormConfigContextValue` | 表单展示配置 Context。 |
1269
+ | Dictionary 类型 | `SchemxDictionary<TValues, TResponse, TOption>` | 函数式选项源配置。 |
1270
+ | 插件类型 | `SchemxInstallOptions` | 基于 Core `SchemxConfig` 的 App 默认配置;Vue 通过 `SchemxConfigDefinition` 扩展布局组件。 |
1271
+ | Dictionary 类型 | `SchemxWithDictionary` | 为 Props 增加 `dict`。 |
1272
+ | Dictionary 类型 | `UseDictionaryReturn<TOption>` | `useDictionary()` 返回值。 |
1273
+ | Dictionary 类型 | `UseDictOptionsReturn<TOption>` | `UseDictionaryReturn<TOption>` 的弃用别名。 |
1274
+ | 表单类型 | `VueSchemxInstance<TValues>` | `SchemxInstance<TValues>` 的弃用别名。 |
1275
+ | Renderer 类型 | `SchemxVueBaseComponentProps<TValues>` | `SchemxBaseComponentProps<TValues>` 的弃用别名。 |
1276
+ | 表单类型 | `SchemxFormProps<TValues>` | `<Schemx>` 组件 Props 类型。 |
1277
+ | 字段类型 | `FieldInstance<TValues>` | Vue Ref / Computed 桥接后的字段控制器类型。 |
1278
+ | 插槽类型 | `SchemxFieldSlotProps`、`SchemxFieldContentSlotProps`、`SchemxFieldErrorSlotProps`、`SchemxFieldSlotValue`、`SchemxFieldSlots` | Field 插槽参数和插槽映射。 |
1279
+ | 插槽类型 | `SchemxGroupSlotProps`、`SchemxGroupSlots` | Group 插槽参数和插槽映射。 |
1280
+ | 组件类型 | `SchemxFieldProps`、`SchemxGroupProps`、`ConfigProviderProps<TValues>` | Field、Group 和 ConfigProvider Props。 |
1281
+ | 布局类型 | `SchemxColDefinition`、`SchemxRowDefinition`、`SchemxColConfig`、`SchemxRowConfig`、`SchemxLayout`、`SchemxVueLayout`、`SchemxVueConfig`、`SchemxConfig`、`SchemxColComponent`、`SchemxColProps` | Vue 层 Row/Col 配置扩展点、兼容类型、表单配置和布局组件类型。 |
1282
+ | 按钮类型 | `SchemxFormActionConfig`、`SchemxFormAction` | 内置提交 / 重置按钮配置。 |
1283
+ | Selector 类型 | `UseFormSelectorOptions<TSelected>` | `useFormSelector` 的比较和刷新配置。 |
1118
1284
 
1119
1285
  根入口没有名为 `SchemxForm` 的命名导出。
1120
1286
 
1121
1287
  ### Core 传递运行时值
1122
1288
 
1123
- | 分类 | 导出 | 用途 |
1124
- | ------------- | ----------------------------- | -------------------------------------------- |
1125
- | 表单 | `createForm` | 创建 Core 表单。 |
1126
- | 字段 | `createField` | 创建 Core 字段控制器。 |
1127
- | Schema source | `createSchemas` | 创建可更新 Schema source。 |
1128
- | Schema source | `isSchemxSchemas` | 判断 Schema source。 |
1129
- | Effect | `createSignalEffect` | 创建 Core signal effect。 |
1130
- | Effect | `runSignalUntracked` | 在不追踪 signal 依赖的上下文中执行函数。 |
1131
- | Watch | `createSignalWatch` | 监听 signal source 的变化。 |
1132
- | Watch | `createDebouncedSignalWatch` | 监听 signal source,并提供 debounce 控制器。 |
1133
- | 配置 | `configureSchemx` | 设置 Core 模块级默认配置。 |
1134
- | 配置 | `getGlobalSchemxConfig` | 读取 Core 模块级默认配置。 |
1135
- | 配置 | `mergeSchemxConfig` | 按优先级纯合并配置。 |
1136
- | 配置 | `resolveSchemxConfig` | 补齐 `schemaConfig` 默认值。 |
1137
- | 配置 | `mergeAndResolveSchemxConfig` | 合并配置并补齐默认值。 |
1138
- | 配置 | `defaultSchemxConfig` | Core 内置字段默认值。 |
1139
- | 配置 | `defaultSchemxConfigKeys` | 当前默认配置 key 集合。 |
1140
- | 配置 | `excludeSchemxConfigKeys` | 不参与字段默认配置的 key。 |
1141
- | Watch | `createWatch` | 分发 Core Watch。 |
1142
- | Watch | `createWatchField` | 单字段 Core Watch。 |
1143
- | Watch | `createWatchFields` | 多字段 Core Watch。 |
1144
- | Watch | `createWatchAll` | 全表 Core Watch。 |
1145
- | Registry | `createRendererRegistry` | 创建 Renderer Registry。 |
1146
- | Registry | `createPresetRuleRegistry` | 创建 PresetRuleRegistry。 |
1147
- | Schema 守卫 | `isFieldSchema` | 判断原始普通字段。 |
1148
- | Schema 守卫 | `isGroupSchema` | 判断原始 Group。 |
1149
- | Schema 守卫 | `isDependencySchema` | 判断原始 Dependency。 |
1150
- | 路径 | `getByPath` | 读取嵌套路径。 |
1151
- | 路径 | `setByPath` | 写入嵌套路径。 |
1152
- | 路径 | `collectObjectPathsByLeaf` | 收集叶子路径。 |
1289
+ | 分类 | 导出 | 用途 |
1290
+ | --------------- | --------------------------------------------------------------------- | --------------------------------------------------------- |
1291
+ | 表单 | `createForm` | 创建 Core 表单。 |
1292
+ | 字段 | `createField` | 创建 Core 字段控制器。 |
1293
+ | Schema source | `createSchemas` | 创建可更新 Schema source。 |
1294
+ | Schema source | `isSchemxSchemas` | 判断 Schema source。 |
1295
+ | Effect | `createSignalEffect` | 创建 Core signal effect。 |
1296
+ | Effect | `runSignalUntracked` | 在不追踪 signal 依赖的上下文中执行函数。 |
1297
+ | Watch | `createSignalWatch` | 监听 signal source 的变化。 |
1298
+ | Watch | `createDebouncedSignalWatch` | 监听 signal source,并提供 debounce 控制器。 |
1299
+ | 配置 | `configureSchemx` | 设置 Core 模块级默认配置。 |
1300
+ | 配置 | `getGlobalSchemxConfig` | 读取 Core 模块级默认配置。 |
1301
+ | 配置 | `mergeConfig` | 按优先级纯合并配置。 |
1302
+ | 配置 | `resolveSchemxConfig` | 补齐 `schemaConfig` 默认值。 |
1303
+ | 配置 | `mergeAndResolveSchemxConfig` | 合并配置并补齐默认值。 |
1304
+ | 配置 | `defaultSchemxConfig` | Core 内置框架无关字段默认值;UI 展示默认值由 Vue 层提供。 |
1305
+ | 配置 | `defaultSchemxConfigKeys` | 当前默认配置 key 集合。 |
1306
+ | 配置 | `excludeSchemxConfigKeys` | 不参与字段默认配置的 key。 |
1307
+ | Watch | `createWatch` | 分发 Core Watch。 |
1308
+ | Watch | `createWatchField` | 单字段 Core Watch。 |
1309
+ | Watch | `createWatchFields` | 多字段 Core Watch。 |
1310
+ | Watch | `createWatchAll` | 全表 Core Watch。 |
1311
+ | Registry | `createRendererRegistry` | 创建 Renderer Registry。 |
1312
+ | Registry | `createPresetRuleRegistry` | 创建 PresetRuleRegistry。 |
1313
+ | Schema 守卫 | `isFieldSchema` | 判断原始普通字段。 |
1314
+ | Schema 守卫 | `isGroupSchema` | 判断原始 Group。 |
1315
+ | Schema 守卫 | `isDependencySchema` | 判断原始 Dependency。 |
1316
+ | Schema 守卫 | `isDynamicSchema` | 判断原始 Dynamic 数组字段。 |
1317
+ | ViewSchema 守卫 | `isSchemxViewFieldSchema`、`isViewGroupSchema`、`isViewDynamicSchema` | 判断 ViewSchema 分支。 |
1318
+ | 路径 | `getByPath` | 读取嵌套路径。 |
1319
+ | 路径 | `setByPath` | 写入嵌套路径。 |
1320
+ | 路径 | `collectObjectPathsByLeaf` | 收集叶子路径。 |
1153
1321
 
1154
1322
  ### Core 传递类型
1155
1323
 
1156
- | 分类 | 导出 | 用途 |
1157
- | ------------------ | ------------------------------- | --------------------------------------------------------------------- |
1158
- | Effect | `SignalEffectOptions` | signal effect 配置。 |
1159
- | Effect | `SignalEffectDispose` | signal effect 的 dispose 函数类型。 |
1160
- | Watch | `SignalWatchOptions` | signal watch 配置。 |
1161
- | Watch | `DebouncedSignalWatchOptions` | 带 debounce 的 signal watch 配置。 |
1162
- | Watch | `DebouncedSignalWatchControls` | 带 debounce 的 signal watch 控制器。 |
1163
- | Watch | `CreateWatchOptions` | Watch 选项。 |
1164
- | Watch | `CreateWatchReturn` | Watch 取消函数。 |
1165
- | Watch | `WatchFieldCallback` | 单字段 Watch callback。 |
1166
- | Watch | `WatchFieldsCallback` | 多字段 Watch callback。 |
1167
- | Watch | `WatchAllCallback` | 全表 Watch callback。 |
1168
- | 表单 | `CreateFormOptions` | Core 表单创建选项。 |
1169
- | 表单 | `FormSchemaOptions` | Schema、初始值和 `schemaConfig` 配置。 |
1170
- | 表单 | `FormRegistryOptions` | Renderer、Rule Registry 和 adapter 配置。 |
1171
- | 表单 | `FormCallbackOptions` | 提交、值变化和规则错误回调。 |
1172
- | 表单 | `FormLifecycleOptions` | Runtime 生命周期钩子。 |
1173
- | 表单 | `ResolvedCreateFormOptions` | 已归一化的 Form 创建配置。 |
1174
- | 表单 | `SchemxInstance` | Core 表单实例接口。 |
1175
- | 基础 | `Values` | 表单值基础约束。 |
1176
- | 基础 | `Dynamic` | 静态值或同步 / 异步值函数。 |
1177
- | 路径 | `NamePath` | 类型安全字段路径。 |
1178
- | 路径 | `FieldValue` | 从路径提取字段值。 |
1179
- | 工具类型 | `DeepReadonly` | 深层只读类型。 |
1180
- | 工具类型 | `CSSProperties` | CSS 属性类型。 |
1181
- | Schema source | `SchemxSchemas` | 可更新 Schema source。 |
1182
- | Schema source | `SchemxSchemasInput` | Schema 数组或 source 联合。 |
1183
- | Schema source | `SchemxSchemasListener` | Schema source listener |
1184
- | 字段 | `SchemxFieldInstance` | Core 字段控制器。 |
1185
- | 字段数组 | `FieldArrayItemValue` | 数组字段行值类型。 |
1186
- | 字段数组 | `FieldArrayPath` | 数组字段路径类型。 |
1187
- | 表单 | `SchemxFormApi` | 传递给动态 Schema 回调的表单 API。 |
1188
- | 表单 | `SchemxFieldRulesMap` | 按字段路径配置的规则映射。 |
1189
- | Schema | `SchemxBase` | 普通字段基础接口。 |
1190
- | Schema | `SchemxBaseField` | Renderer key 分布的字段联合。 |
1191
- | Schema | `SchemxExactBaseField` | 保留具体 Renderer key 的字段类型。 |
1192
- | Schema | `SchemxGroupField` | 原始 Group Schema。 |
1193
- | Schema | `SchemxDependencyField` | 原始 Dependency Schema。 |
1194
- | Schema | `SchemxField` | 全部原始 Schema 联合。 |
1195
- | Schema | `SchemxBaseComponentProps` | Renderer 公共 Props |
1196
- | Schema | `SchemxComponentProps` | Renderer 专属与公共 Props |
1197
- | Schema | `SchemxFormItemProps` | Core 保留的字段展示 Props 类型(schema 属性名仍为 `formItemProps`)。 |
1198
- | 扩展 | `SchemxFieldDefinition` | 普通字段声明合并接口。 |
1199
- | 扩展 | `SchemxGroupFieldDefinition` | Group 声明合并接口。 |
1200
- | 依赖 | `SchemxFieldDependencies` | 普通字段的动态属性与触发字段配置。 |
1201
- | 依赖 | `SchemxGroupDependencies` | Group 容器的动态状态配置。 |
1202
- | 依赖 | `SchemxDependencyDependencies` | Dependency 容器的动态状态配置。 |
1203
- | 依赖 | `SchemxContainerDependencies` | Group/Dependency 容器动态状态配置。 |
1204
- | 依赖 | `SchemxConditionFn` | 动态属性条件函数。 |
1205
- | ViewSchema | `SchemxViewDebugMeta` | ViewSchema 诊断元数据。 |
1206
- | ViewSchema | `SchemxViewFieldSchema` | 字段渲染投影。 |
1207
- | ViewSchema | `SchemxViewGroupSchema` | Group 渲染投影。 |
1208
- | ViewSchema | `SchemxViewSchema` | 字段 / Group 投影联合。 |
1209
- | 配置 | `MergedSchemxConfig` | 已合并且补齐 `schemaConfig` 默认值。 |
1210
- | 配置 | `SchemxConfig` | Core 模块级和 Form/App 可继承配置。 |
1211
- | 配置 | `SchemxSchemaConfig` | 表单级字段默认展示与校验配置。 |
1212
- | 配置 | `SchemxConfigKey` | 当前默认配置 key 类型。 |
1213
- | 配置 | `ExcludeSchemxConfigKeys` | 排除配置 key 类型。 |
1214
- | Renderer | `SchemxRendererKey` | Renderer key 类型。 |
1215
- | Renderer | `SchemxRendererDefinition` | Renderer Props 声明合并接口。 |
1216
- | Renderer Registry | `RendererRegistry` | Renderer Registry 实例类型。 |
1217
- | Renderer Registry | `RegistryOptions` | 注册覆盖选项(renderer 与 rule 共享)。 |
1218
- | Renderer Registry | `RendererMap` | Renderer 批量映射。 |
1219
- | Validator | `ValidationRule` | 原生规则接口。 |
1220
- | Validator | `ValidationRuleContext` | 原生规则执行上下文。 |
1221
- | Validator | `ValidationRuleIssue` | 单条规则产生的问题。 |
1222
- | Validator | `ValidationRuleResult` | 单条规则执行结果。 |
1223
- | Validator | `ValidationResult` | 校验成功 / 失败联合。 |
1224
- | Validator | `ValidationSuccess` | 校验成功结果。 |
1225
- | Validator | `ValidationFailure` | 普通校验失败结果。 |
1226
- | Validator | `ValidationCancelled` | 被更新校验或销毁操作中止的结果。 |
1227
- | Validator | `ValidationError` | 校验失败详情。 |
1228
- | Validator | `FieldValidationError` | 单字段错误。 |
1229
- | Validator | `FormValidationError` | 表单级错误。 |
1230
- | Validator | `AdapterRule` | 第三方 adapter 创建的品牌规则。 |
1231
- | Validator | `ValidationAdapterRule` | adapter 接收的第三方规则输入类型。 |
1232
- | Validator | `ValidationAdapterID` | adapter 的唯一标识类型。 |
1233
- | Validator | `ValidationAdapterV1` | 第三方校验 adapter 协议。 |
1234
- | Validator | `ValidationAdapter` | `ValidationAdapterV1` 的兼容别名。 |
1235
- | Validator | `ValidationAdapterRegistration` | adapter 注册及覆盖选项。 |
1236
- | Validator | `ValidationAdapterOption` | adapter 或带覆盖选项的注册项。 |
1237
- | Validator | `ValidationTrigger` | 校验触发时机。 |
1238
- | Validator | `StandardSchemaV1` | Standard Schema v1 协议。 |
1239
- | Rule | `PresetRuleDefinition` | 自定义规则声明合并接口。 |
1240
- | Rule | `PresetRuleName` | 声明合并推导的规则 key。 |
1241
- | Rule | `RequiredOptions` | 必填消息与空值判断配置。 |
1242
- | Rule | `RequiredConfig` | 布尔必填开关或必填配置对象。 |
1243
- | Rule | `DefinedFieldValue` | 从表单值和路径提取已定义字段值。 |
1244
- | Rule | `FieldRule` | 单个字段规则联合类型。 |
1245
- | Rule | `FieldRules` | Standard Schema、内置或自定义规则。 |
1246
- | Validator Registry | `PresetRuleRegistry` | PresetRuleRegistry 实例类型。 |
1247
- | Validator Registry | `PresetRuleFactoryContext` | 规则工厂接收的字段上下文。 |
1248
- | Validator Registry | `PresetRuleFactory` | 按字段 Schema 生成规则的工厂。 |
1249
- | Validator Registry | `PresetRuleEntry` | Standard Schema、原生规则或工厂联合。 |
1250
- | Validator Registry | `PresetRuleMap` | 规则名到条目的批量映射。 |
1251
- | Validator Registry | `PresetRuleRegistryChange` | Registry 变更事件。 |
1252
- | Validator Registry | `PresetRuleRegistryListener` | Registry 变更监听器。 |
1324
+ | 分类 | 导出 | 用途 |
1325
+ | ------------------ | -------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------ |
1326
+ | Effect | `SignalEffectOptions` | signal effect 配置。 |
1327
+ | Effect | `SignalEffectDispose` | signal effect 的 dispose 函数类型。 |
1328
+ | Watch | `SignalWatchOptions` | signal watch 配置。 |
1329
+ | Watch | `DebouncedSignalWatchOptions` | 带 debounce 的 signal watch 配置。 |
1330
+ | Watch | `DebouncedSignalWatchControls` | 带 debounce 的 signal watch 控制器。 |
1331
+ | Watch | `CreateWatchOptions` | Watch 选项。 |
1332
+ | Watch | `CreateWatchReturn` | Watch 取消函数。 |
1333
+ | Watch | `WatchFieldCallback` | 单字段 Watch callback。 |
1334
+ | Watch | `WatchFieldsCallback` | 多字段 Watch callback。 |
1335
+ | Watch | `WatchAllCallback` | 全表 Watch callback。 |
1336
+ | 表单 | `CreateFormOptions` | Core 表单创建选项。 |
1337
+ | 表单 | `FormSchemaOptions` | Schema、初始值和 `schemaConfig` 配置。 |
1338
+ | 表单 | `FormRegistryOptions` | Renderer、Rule Registry 和 adapter 配置。 |
1339
+ | 表单 | `FormCallbackOptions` | 提交、值变化和规则错误回调。 |
1340
+ | 表单 | `FormLifecycleOptions` | Runtime 生命周期钩子。 |
1341
+ | 表单 | `FormPerformanceOptions` | Scheduler 与整表校验并发配置。 |
1342
+ | 表单 | `ResolvedCreateFormOptions` | 已归一化的 Form 创建配置。 |
1343
+ | 表单 | `SchemxInstance` | Core 表单实例接口。 |
1344
+ | 基础 | `Values` | 表单值基础约束。 |
1345
+ | 基础 | `Dynamic` | 静态值或同步 / 异步值函数。 |
1346
+ | 路径 | `NamePath` | 类型安全字段路径。 |
1347
+ | 路径 | `FieldValue` | 从路径提取字段值。 |
1348
+ | 值更新 | `SetValueAction`、`SetValuesAction` | `setFieldValue()` / `setFieldsValue()` 的值或 updater 类型。 |
1349
+ | 工具类型 | `DeepReadonly` | 深层只读类型。 |
1350
+ | 工具类型 | `CSSProperties` | CSS 属性类型。 |
1351
+ | Schema source | `SchemxSchemas` | 可更新 Schema source。 |
1352
+ | Schema source | `SchemxSchemasInput` | Schema 数组或 source 联合。 |
1353
+ | Schema source | `SchemxSchemasListener` | Schema source listener。 |
1354
+ | 字段 | `SchemxFieldInstance` | Core 字段控制器。 |
1355
+ | 字段数组 | `FieldArrayItemValue` | 数组字段行值类型。 |
1356
+ | 字段数组 | `FieldArrayPath` | 数组字段路径类型。 |
1357
+ | 字段数组 | `FieldArrayChange` | 数组结构变化的变更描述。 |
1358
+ | 表单 | `SchemxFormApi` | 传递给动态 Schema 回调的表单 API。 |
1359
+ | 表单 | `SchemxFieldRulesMap` | 按字段路径配置的规则映射。 |
1360
+ | Schema | `SchemxBase` | 普通字段基础接口。 |
1361
+ | Schema | `SchemxBaseField` | Renderer key 分布的字段联合。 |
1362
+ | Schema | `SchemxExactBaseField` | 保留具体 Renderer key 的字段类型。 |
1363
+ | Schema | `SchemxGroupField` | 原始 Group Schema |
1364
+ | Schema | `SchemxDependencyField` | 原始 Dependency Schema |
1365
+ | Schema | `SchemxField` | 全部原始 Schema 联合。 |
1366
+ | Schema | `SchemxDynamicField`、`SchemxDynamicArrayPath`、`SchemxDynamicNamePath` | Dynamic 数组 Schema 与路径类型。 |
1367
+ | Schema | `SchemxDynamicItemSchema`、`SchemxDynamicItemGroup`、`SchemxDynamicItemDependency`、`SchemxDynamicItemDependencyRendererContext` | Dynamic 行模板类型。 |
1368
+ | Schema | `SchemxBaseComponentProps` | Core Renderer 公共 Props。 |
1369
+ | Schema | `SchemxCoreBaseComponentProps`、`SchemxRendererPropsMap` | Core 公共 Props 与默认 Props 映射。 |
1370
+ | Schema | `SchemxFormItemProps` | Field 展示 Props。 |
1371
+ | Schema | `SchemxColConfig`、`SchemxRowConfig` | Vue 层的 Col/Row 元数据类型。 |
1372
+ | Schema | `SchemxLayout` | Vue 层兼容期保留的旧布局元数据类型,已弃用。 |
1373
+ | Schema | `SchemxBaseComponentProps` | Renderer 公共 Props。 |
1374
+ | Schema | `SchemxComponentProps` | Renderer 专属与公共 Props。 |
1375
+ | 扩展 | `SchemxComponentPropsDefinition` | Renderer 公共 Props 的声明合并扩展点。 |
1376
+ | 扩展 | `SchemxFieldDefinition` | 普通字段声明合并接口。 |
1377
+ | 扩展 | `SchemxGroupFieldDefinition` | Group 声明合并接口。 |
1378
+ | 依赖 | `SchemxFieldDependencies` | 普通字段的动态属性与触发字段配置。 |
1379
+ | 依赖 | `SchemxFieldDependenciesDefinition` | 字段依赖配置的适配层声明合并扩展点。 |
1380
+ | 依赖 | `SchemxGroupDependencies` | Group 容器的动态状态配置。 |
1381
+ | 依赖 | `SchemxDependencyDependencies` | Dependency 容器的动态状态配置。 |
1382
+ | 依赖 | `SchemxContainerDependencies` | Group/Dependency 容器动态状态配置。 |
1383
+ | 依赖 | `SchemxConditionFn` | 动态属性条件函数。 |
1384
+ | 依赖 | `SchemxDynamicDependencies` | Dynamic 容器动态状态配置。 |
1385
+ | 依赖 | `SchemxFieldDependenciesConditionKey`、`SchemxFieldDependenciesStaticProps` | 字段依赖属性的键和值类型。 |
1386
+ | ViewSchema | `SchemxViewDebugMeta` | ViewSchema 诊断元数据。 |
1387
+ | ViewSchema | `SchemxViewFieldSchema` | 字段渲染投影。 |
1388
+ | ViewSchema | `SchemxViewGroupSchema` | Group 渲染投影。 |
1389
+ | ViewSchema | `SchemxViewDynamicItem`、`SchemxViewDynamicSchema` | Dynamic 数组行及容器渲染投影。 |
1390
+ | ViewSchema | `SchemxViewSchema` | 字段 / Group 投影联合。 |
1391
+ | 配置 | `MergedSchemxConfig` | 已合并且补齐 `schemaConfig` 默认值。 |
1392
+ | 配置 | `SchemxConfig` | Core 模块级和 Form/App 可继承配置。 |
1393
+ | 配置 | `SchemxSchemaConfig` | 表单级字段默认展示与校验配置。 |
1394
+ | 配置 | `SchemxSchemaConfigDefinition` | 表单级 Schema 配置的适配层声明合并扩展点。 |
1395
+ | 配置 | `SchemxConfigKey` | 当前默认配置 key 类型。 |
1396
+ | 配置 | `ExcludeSchemxConfigKeys` | 排除配置 key 类型。 |
1397
+ | Renderer | `SchemxRendererKey` | Renderer key 类型。 |
1398
+ | Renderer | `SchemxRendererDefinition` | Renderer Props 声明合并接口。 |
1399
+ | Renderer Registry | `RendererRegistry` | Renderer Registry 实例类型。 |
1400
+ | Renderer Registry | `RegistryOptions` | 注册覆盖选项(renderer 与 rule 共享)。 |
1401
+ | Renderer Registry | `RendererMap` | Renderer 批量映射。 |
1402
+ | Validator | `ValidationRule` | 原生规则接口。 |
1403
+ | Validator | `ValidationRuleContext` | 原生规则执行上下文。 |
1404
+ | Validator | `ValidationRuleIssue` | 单条规则产生的问题。 |
1405
+ | Validator | `ValidationRuleResult` | 单条规则执行结果。 |
1406
+ | Validator | `ValidationResult` | 校验成功 / 失败联合。 |
1407
+ | Validator | `ValidationSuccess` | 校验成功结果。 |
1408
+ | Validator | `ValidationFailure` | 普通校验失败结果。 |
1409
+ | Validator | `ValidationCancelled` | 被更新校验或销毁操作中止的结果。 |
1410
+ | Validator | `ValidationError` | 校验失败详情。 |
1411
+ | Validator | `FieldValidationError` | 单字段错误。 |
1412
+ | Validator | `FormValidationError` | 表单级错误。 |
1413
+ | Validator | `AdapterRule` | 第三方 adapter 创建的品牌规则。 |
1414
+ | Validator | `ValidationAdapterRule` | adapter 接收的第三方规则输入类型。 |
1415
+ | Validator | `ValidationAdapterID` | adapter 的唯一标识类型。 |
1416
+ | Validator | `ValidationAdapterV1` | 第三方校验 adapter 协议。 |
1417
+ | Validator | `ValidationAdapter` | `ValidationAdapterV1` 的兼容别名。 |
1418
+ | Validator | `ValidationAdapterRegistration` | adapter 注册及覆盖选项。 |
1419
+ | Validator | `ValidationAdapterOption` | adapter 或带覆盖选项的注册项。 |
1420
+ | Validator | `ValidationTrigger` | 校验触发时机。 |
1421
+ | Validator | `StandardSchemaV1` | Standard Schema v1 协议。 |
1422
+ | Validator | `AsyncValidatorRule` | async-validator 单条规则。 |
1423
+ | Validator | `AsyncValidatorDescriptor` | async-validator 单条或多条规则描述。 |
1424
+ | Rule | `PresetRuleDefinition` | 自定义规则声明合并接口。 |
1425
+ | Rule | `PresetRuleName` | 声明合并推导的规则 key。 |
1426
+ | Rule | `RequiredOptions` | 必填消息与空值判断配置。 |
1427
+ | Rule | `RequiredConfig` | 布尔必填开关或必填配置对象。 |
1428
+ | Rule | `DefinedFieldValue` | 从表单值和路径提取已定义字段值。 |
1429
+ | Rule | `FieldRule` | 单个字段规则联合类型。 |
1430
+ | Rule | `FieldRules` | Standard Schema、内置或自定义规则。 |
1431
+ | Validator Registry | `PresetRuleRegistry` | PresetRuleRegistry 实例类型。 |
1432
+ | Validator Registry | `PresetRuleFactoryContext` | 规则工厂接收的字段上下文。 |
1433
+ | Validator Registry | `PresetRuleFactory` | 按字段 Schema 生成规则的工厂。 |
1434
+ | Validator Registry | `PresetRuleEntry` | Standard Schema、原生规则或工厂联合。 |
1435
+ | Validator Registry | `PresetRuleMap` | 规则名到条目的批量映射。 |
1436
+ | Validator Registry | `PresetRuleRegistryChange` | Registry 变更事件。 |
1437
+ | Validator Registry | `PresetRuleRegistryListener` | Registry 变更监听器。 |