DynamicForm 动态表单
动态表单组件,用于快速构建基于配置的表单界面。
TIP
除了完整的动态表单组件,我们也提供了独立的 EzFormItem 组件,可以用于构建自定义表单布局。
组件概述
DynamicForm 用于把常见表单页面抽象成“配置驱动”的方式构建。相比手写大量 el-form-item,它更适合字段较多、结构相对规则、需要快速迭代的业务表单场景。
它当前主要解决这几类问题:
- 通过
items快速声明单分组表单,适合作为简单场景下的快捷写法。 - 通过
groups把表单拆成多个正式分组,支持标题、描述、分组级布局和分组插槽。 - 内置常见表单组件类型、必填规则、显隐联动、禁用联动,减少重复样板代码。
- 同时保留字段级插槽和分组级插槽,便于在标准化配置和高度定制化之间切换。
推荐使用原则:
groups是标准模式,适合作为长期维护的正式配置模型。items是单分组场景的 shorthand,适合简单表单或临时查询区。- 如果某一块布局已经明显超出“配置生成”的边界,可以结合
EzFormItem或分组插槽单独定制。 - 使用
cols做栅格布局时,不建议再传inline给el-form,否则容易和栅格分栏产生布局冲突。
基础用法
组件类型
表单校验
自定义插槽
分组表单
字段序列化
属性
| 属性名 | 说明 | 类型 | 是否必须 | 默认值 |
|---|---|---|---|---|
| v-model | 表单双向绑定数据 | Record | 否 | {} |
| items | 单分组场景的简写配置 | FormItemConfig[] | 否 | [] |
| groups | 标准分组配置(推荐) | FormGroupConfig[] | 否 | [] |
| cols | 栅格布局列数 | number | 否 | 1 |
| gutter | 栅格间距 | number | 否 | 20 |
| 其他 Form 属性 | 通过组件属性透传给 el-form | Partial<Omit<FormProps, 'model' | 'rules' | 'showMessage'>> | 否 | - |
FormItemConfig
| 属性名 | 说明 | 类型 | 是否必须 | 默认值 |
|---|---|---|---|---|
| prop | 字段名 | string | 是 | - |
| label | 标签 | string | 否 | - |
| type | 组件类型。内建分支仅接受 FormItemType 字面量;自定义组件场景使用 component 即可 | FormItemType | 否 | - |
| defaultValue | 默认值 | any | 否 | - |
| rules | 验证规则 | FormItemRule | 否 | - |
| required | 是否必填 | boolean | 否 | false |
| requiredMessage | 必填提示信息 | string | 否 | - |
| span | 占用栅格列数 | number | 否 | - |
| hidden | 是否隐藏 | boolean | 否 | false |
| disabled | 是否禁用 | boolean | 否 | false |
| placeholder | 占位符 | string | 否 | - |
| options | 选项配置。select 支持分组选项,radio/checkbox 使用各自选项类型,tree-select/cascader 按结构化数据源透传 | FormItemOption[] | 否 | - |
| attrs | 组件属性(透传给具体组件)。select/radio/checkbox/upload-images、tree-select、cascader 会按各自公开字段子集提供更明确的类型提示,其他内建控件保持宽透传 | Record | 否 | - |
| component | 自定义字段组件。需要遵循 modelValue / update:modelValue / disabled 契约 | Component | 否 | - |
| itemAttrs | 额外的 el-form-item 属性 | Partial<FormItemProps> | 否 | - |
| show | 联动显示条件 | Function | 否 | - |
| disabledWhen | 联动禁用条件 | Function | 否 | - |
| serialize | 提交前字段序列化 | Function | 否 | - |
| deserialize | 外部数据回填时的字段反序列化 | Function | 否 | - |
FormGroupConfig
| 属性名 | 说明 | 类型 | 是否必须 | 默认值 |
|---|---|---|---|---|
| name | 分组唯一标识 | string | 否 | - |
| title | 分组标题 | string | 否 | - |
| description | 分组描述 | string | 否 | - |
| items | 分组下的表单项 | FormItemConfig[] | 是 | [] |
| cols | 分组内栅格列数 | number | 否 | 继承全局 cols |
| gutter | 分组内栅格间距 | number | 否 | 继承全局 gutter |
| hidden | 是否隐藏分组 | boolean | 否 | false |
| show | 分组联动显示条件 | Function | 否 | - |
| className | 分组容器 class | string | 否 | - |
| style | 分组容器 style | string | Record | 否 | - |
| headerClassName | 分组头部 class | string | 否 | - |
| headerStyle | 分组头部 style | string | Record | 否 | - |
| bodyClassName | 分组主体 class | string | 否 | - |
| bodyStyle | 分组主体 style | string | Record | 否 | - |
| headerSlot | 自定义分组头插槽名 | string | 否 | group-header-${name} |
| slot | 自定义分组内容插槽名 | string | 否 | group-${name} |
数据初始化与双向绑定
- v-model:通过
v-model进行双向绑定,表单项的修改会实时同步到外部。 - defaultValue:配置项的默认值,仅在绑定的 model 对象中不存在该字段时,会在初始化时自动补全。
- items / groups 互斥:
items和groups不能同时传入,组件会直接报错。 - 模式定位:
groups是正式配置模型;items只是单分组快捷写法,不再扩展分组级能力。 - 类型约束:
FormItemConfig现在会针对select、radio、checkbox、tree-select、cascader、upload-images、component这些分支提供更明确的attrs/options约束;其中tree-select与cascader也收敛到了稳定的 attrs 子集。 - 自定义组件契约:
component分支不再是“任意组件都可以”,而是默认要求满足字段组件协议。
数据流设计
本组件支持 Vue 3 标准的 v-model 双向绑定:
- 推荐使用
v-model驱动数据,确保表单与业务逻辑数据实时同步。 - 使用
getFormData()获取当前表单数据的副本(深拷贝)。 - 使用
getSubmitData()获取应用字段级serialize后的提交数据。 - 使用
setFormData()显式合并或替换数据。 - 使用
setSubmitData()将提交态数据反序列化后回填到表单模型。未声明为表单prop的额外提交字段不会写入v-model。 - 使用
captureInitialData()记录当前表单状态为新的重置基线。 - 使用
resetForm()将表单恢复到当前基线数据。
提示
- 组件内部会通过
ensureStateStructure自动补全items或groups中定义的prop键,以确保 Element Plus 的校验追踪能正常工作。 - 即使
v-model绑定的是一个空的reactive或ref对象,组件也会在挂载或外部替换数据后根据配置自动初始化结构。 setFormData()在合并或替换数据后会自动补齐缺失字段,并清空当前校验状态。getSubmitData()不会修改当前v-model,它只返回应用字段级serialize后的新对象。setSubmitData()只会回填已声明的表单字段,因此诸如拆分后的日期字段这类请求态字段可以留在 UI 模型之外。- 组件会在首次挂载完成后自动记录一份初始化快照,
resetForm()默认恢复到这份快照。
FormItemType
| 名称 | 说明 |
|---|---|
| INPUT | 输入框 |
| TEXTAREA | 多行文本 |
| NUMBER | 数字输入 |
| PASSWORD | 密码输入 |
| SELECT | 下拉选择(封装组件) |
| RADIO | 单选框(封装组件) |
| CHECKBOX | 多选框(封装组件) |
| DATE | 日期选择 |
| DATETIME | 日期时间 |
| DATERANGE | 日期范围 |
| DATETIMERANGE | 日期时间范围 |
| TIME | 时间选择 |
| TIMERANGE | 时间范围 |
| UPLOAD_IMAGES | 图片上传(封装组件) |
| SWITCH | 开关 |
| TREE_SELECT | 树形选择 |
| CASCADER | 级联选择 |
| SLIDER | 滑块 |
| RATE | 评分 |
方法
| 方法名 | 说明 | 类型 |
|---|---|---|
| validate | 验证表单 | Function |
| validateField | 验证指定字段 | Function |
| clearValidate | 清空验证 | Function |
| getFormData | 获取表单数据(按需调用) | Function |
| getSubmitData | 获取应用字段序列化后的提交数据 | Function |
| setFormData | 设置表单数据(会清除校验,支持合并或完全替换) | Function |
| setSubmitData | 设置提交态数据并反序列化回填 | Function |
| resetForm | 重置表单到当前基线数据 | Function |
| captureInitialData | 将当前表单状态记录为新的基线 | Function |
插槽
| 插槽名 | 说明 | 参数 |
|---|---|---|
[prop] | 自定义表单项内容 | { item: FormItemConfig, value: any, formData: Record } |
label-[prop] | 自定义表单项标签 | { item: FormItemConfig } |
group-header | 通用分组头插槽 | { group: FormGroupConfig, index: number, items: FormItemConfig[], formData: Record } |
group | 通用分组内容插槽 | { group: FormGroupConfig, index: number, items: FormItemConfig[], formData: Record } |
group-header-[name] | 指定分组头插槽 | { group: FormGroupConfig, index: number, items: FormItemConfig[], formData: Record } |
group-[name] | 指定分组内容插槽 | { group: FormGroupConfig, index: number, items: FormItemConfig[], formData: Record } |