ProForm
ProForm 是基于 Ant Design Vue Form 的高级表单封装,提供了更简洁的表单数据管理和字段配置方式。
何时使用
- 需要通过配置生成表单而不是编写大量模板代码
- 需要表单字段的动态增减
- 需要统一表单布局和样式
配合 useForm 使用
antd-vue-pro 导出了一个名为 useForm 的自定义 Hook,用于处理表单数据和字段配置,配合 useForm 可以更轻松地使用 ProForm。
架构与数据流

ProForm 的渲染链路可以理解为三层组件协作:
ProForm负责承接useForm的formData和fieldsBaseFormItem负责将fields拆分为 FormItem / GridItem / 组件 props,并递归渲染BaseField负责把字段配置映射为具体 UI 组件并处理 v-model
数据流的核心路径如下:
useForm创建formData+fieldsProForm将formData作为Form的modelBaseField使用v-model:[modelProp]双向绑定字段值valueFormatter在值回写前处理数据,再由setFormData更新FormItem在字段更新时触发校验(通过内部onFieldChange)
快速开始
最小使用步骤:
- 使用
useForm创建表单对象 - 将表单对象传给
ProForm
<script setup lang="ts">
import { ProForm, useForm } from '@qin-ui/antd-vue-pro';
type FormData = {
name: string;
};
const form = useForm<FormData>({ name: '' }, [
{ label: '姓名', path: 'name', component: 'input' },
]);
</script>
<template>
<ProForm :form="form" />
</template>API
Props
| 参数名 | 说明 | 类型 | 默认值 |
|---|---|---|---|
| form | useForm 返回对象 | Form | - |
| grid | 是否启用栅格布局 | boolean | GridProps | false |
| ... | 继承 Ant Design Vue Form 组件的所有参数 | FormProps | - |
Events
| 事件名 | 说明 | 类型 |
|---|---|---|
| ... | 继承 Ant Design Vue Form 组件的所有事件 | FormEvents |
Methods
| 方法名 | 说明 | 类型 |
|---|---|---|
| ... | 继承 Ant Design Vue Form 组件的所有方法 | FormMethods |
Field 配置
Field 是 ProForm 的字段配置入口,单个字段的属性会被拆分到 FormItem / GridItem / 具体组件等层级。
Base(公共字段)
去向:公共属性会被 BaseFormItem/BaseField 解析并分发到对应层级。
| 字段 | 说明 |
|---|---|
path | 字段标识 namePath,同 FormItem 的 name |
hidden | 字段是否隐藏 |
disabled | 字段是否禁用 |
label | 字段标题,支持字符串或 VNode |
slots | 字段插槽配置(FormItem 与组件插槽) |
formItemStyle | FormItem 样式 |
formItemClass | FormItem 类名 |
formItemContainer | FormItem 外层包裹组件 |
formItemDataAttrs | 附加到 FormItem DOM 的属性 |
componentStyle | 组件样式(仅非嵌套字段有效) |
componentClass | 组件类名(仅非嵌套字段有效) |
componentContainer | 组件外层包裹组件(仅非嵌套字段有效) |
componentDataAttrs | 附加到组件 DOM 的属性(仅非嵌套字段有效) |
valueFormatter | 值格式化 get/set 或单函数(仅非嵌套字段有效);双参 (val, oldVal) 声明才注入旧值快照 |
modelProp | v-model 属性名,默认 value(仅非嵌套字段有效) |
extraProps | 不参与渲染,仅用于业务侧自定义标识 |
注意:
component是 Field 级别的属性(不在 Base 类型中),用于指定渲染的组件名称或组件对象。对于内置组件,类型为组件名字符串(如'input'、'select');对于自定义组件,需配合'custom'类型使用或通过ProComponentProvider注册。
componentStyle/componentClass/componentContainer/valueFormatter/modelProp/componentDataAttrs仅对非嵌套字段(即不含fields子字段的字段)有效。嵌套字段使用grid控制布局。
Nested(嵌套字段)
去向:递归进入下一层 BaseFormItem。
| 字段 | 说明 |
|---|---|
fields | 嵌套子字段配置 |
grid | 嵌套字段的网格布局开关或参数 |
FormItem 透传
去向:传给 FormItem。
- 继承
FormItemProps(不包含label) - 常用字段:
rules、validateStatus、help、extra、required等
GridItem 透传
去向:传给 UIGridItem。
- 继承
GridItemProps - 常用字段:
span、xs、sm、md、lg、xl、xxl
组件透传
去向:传给具体表单组件。
- 除以上分组之外的字段会被当作组件 props 透传
关键示例
示例 1:字段 + valueFormatter
const form = useForm({ name: '' }, [
{
path: 'name',
component: 'input',
valueFormatter: val => (val ? val.trim() : val),
},
]);示例 2:嵌套字段 + grid
const form = useForm({ user: { first: '', last: '' } }, [
{
path: 'user',
grid: true,
fields: [
{ path: 'first', component: 'input', span: 12 },
{ path: 'last', component: 'input', span: 12 },
],
},
]);字段属性分流规则
字段属性会被拆分为四类:GridItem、FormItem、具体组件、容器/插槽。
分流规则
grid/GridItem 相关 props 会传给UIGridItemformItem*/校验/提示等会传给FormItemcomponent*/modelProp/valueFormatter与其余 props 会传给具体组件formItemContainer/componentContainer/slots走容器或插槽fields进入下一层BaseFormItem
优先级说明
- 同名插槽优先于
component渲染 modelProp默认valuevalueFormatter在值回写前执行slots中label/extra/help/tooltip归属FormItem,其余归属组件
Types
Field:字段配置入口,组合组件参数 / FormItem 参数 / GridItem 参数Base:字段公共能力集合(path、slots、容器、样式、格式化等)Fields:字段数组,支持嵌套ValueFormatter:字段值处理函数,支持get/set或单函数modelProp:自定义 v-model 绑定字段名
高级:TypeScript 类型推导与覆盖
在使用 ProForm 的 fields 时,如果想要获得新增自定义组件的类型推导,或强制覆盖内置基础组件(如 input)的属性提示,可以通过 TypeScript 的 声明合并(Declaration Merging) 来扩展全局的 ComponentMap。
在你的业务代码类型声明文件(如 env.d.ts 或 components.d.ts)中补充如下内容:
import 'antd-vue-pro';
import type MyCustomUpload from '@/components/MyCustomUpload.vue';
import type MySuperInput from '@/components/MySuperInput.vue';
declare module 'antd-vue-pro' {
// 扩展 ComponentMap 以支持类型推导
interface ComponentMap {
// 1. 新增组件(例如 'custom-upload'),配置后该组件的 Props 将提供完整提示
'custom-upload': typeof MyCustomUpload;
// 2. 覆盖默认内置组件(例如替换 'input' 的原生 Props 提示为 MySuperInput 的 Props)
input: typeof MySuperInput;
}
}配置生效后:
path对应的component字段名可以正常提示'custom-upload'等自定义值。- 填入对应的
component之后,将自动获得精准的对应组件的 Props 类型校验与代码补全。
扩展点与最佳实践(简版)
- 动态字段:使用
appendField/prependField/deleteField进行增删 - 字段联动:用
setFormData+setField实现显隐、禁用、规则联动 - 自定义组件接入:
component+ProComponentProvider注册,插槽优先级高于component - 值格式化:使用
valueFormatter与modelProp对齐组件的 v-model 习惯
useForm
创建表单对象的hook
参数
| 参数 | 类型 | 说明 | 默认值 |
|---|---|---|---|
initData | DeepPartial<D> | 表单初始数据 | {} |
initFields | Field<D>[] | 表单字段初始配置 | [] |
root | boolean | 是否为根 form 实例(用于嵌套 form 场景) | true |
useForm支持两种调用方式:useForm(initData?, initFields?, root?)或useForm(root?)(仅传入 root 标识获取/创建根表单)。
出参 Form
| 属性名 | 说明 |
|---|---|
| formData | 响应式表单数据对象,可直接读写 |
| getFormData | 根据字段 path 获取字段值,不传 path 返回全部数据 |
| setFormData | 设置字段值:setFormData(path, value) 或 setFormData(path, prev => next) 函数式更新;也可 setFormData(value) 批量覆盖 |
| fields | 字段配置数组(响应式 Ref) |
| setField | 更新字段配置,默认合并(merge),可通过 { updateType: 'rewrite' } 覆盖 |
| getField | 获取字段配置,支持路径字符串或查找函数 f => f.label === '...' |
| deleteField | 删除字段配置,支持 { all: true } 批量删除所有匹配项 |
| appendField | 在指定字段后追加新字段,传 undefined 在末尾追加 |
| prependField | 在指定字段前插入新字段,传 undefined 在开头插入 |
| getParentField | 获取字段所属父级字段配置,一级字段返回虚拟根容器 |
| formRef | 底层 Ant Design Vue Form 组件实例引用(Ref),可调用 validate()、resetFields() 等 |
| setFormRef | 设置 Form 组件实例,由 ProForm 内部自动调用,一般无需手动使用 |