Form 表单
import { ErrorListComponent } from '@apollo-design/ui';具有数据收集、校验和提交功能的表单,包含复选框、单选框、输入框、下拉选择框等元素。
何时使用
- 需要创建一个原生表单,可能包含各种交互式控件;
- 提交前需要校验用户输入(同步/异步规则);
- 需要动态增删表单项(
Form.List)。
引入
import { Form, FormItem, FormList, useForm, useWatch, ErrorList } from '@apollo-design/ui';
// 或复合写法
import { Form } from '@apollo-design/ui';
const { Item, List, useForm, useWatch, ErrorList } = Form;
代码演示
动态表单 #
Form.List 的默认插槽给出 { fields, operations, meta }:fields 用于 v-for 渲染,operations.add/remove/move 操作行。示例支持增删用户,提交后由 message 给出反馈。
嵌套动态表单 #
Form.List 可以嵌套:内层 name 用 [field.name, 'tags'] 定位到父行,字段名路径会按层级展开。示例支持每个用户维护一组标签。
监听字段 #
Form.useWatch(name, form) 返回响应式 Ref;示例在两个输入框下方实时显示字段值,无需额外的 @change 处理。
字段联动 #
确认密码的 FormItem 声明 dependencies: ['password']:密码变化时会重新校验确认框;validator 从表单实例读取当前密码并返回 Promise。
异步校验 #
validator 返回 Promise 时表单进入 validating 状态,has-feedback 显示加载图标;示例输入 admin 会在 600ms 后被拒绝。
初始值与重置 #
initialValues 提供非受控初始值;form.setFieldsValue 可以整体回填,form.resetFields 恢复到初始值。
提交失败 #
@finishFailed 拿到 errorFields;scrollToFirstError 会自动滚动并聚焦到第一条错误。提交成功与失败都在下方给出可见反馈。
读写表单值 #
通过 useForm() 实例调用 getFieldsValue / setFieldsValue,把当前值序列化后展示在页面上;适用于外部按钮触发的批量回填。
禁用与尺寸 #
Form 的 disabled 与 size 会级联到所有表单项;示例可实时切换,验证禁用态与三种尺寸。
滚动到字段 #
form.scrollToField(name, options) 会把字段滚入最近的滚动容器并聚焦。示例容器限高 240px,点击按钮可直接定位到最后一个字段。
高级搜索 #
使用 Row / Col 栅格把多个 Form.Item 排成筛选区,并通过 v-show 控制「展开更多筛选」。Form 的 @finish 会回传所有字段值,useForm 返回的 resetFields() 用于重置查询条件。所有输入控件都带 aria-label,便于辅助技术识别。
复杂表单控件 #
当控件的值与表单存储值不是同一单位时,用 Form.Item 的 getValueProps 把存储值转换成控件展示值,再用 getValueFromEvent 把控件事件转换回存储格式。示例中表单内部以「分」存储金额,InputNumber 展示与输入的是「元」;useWatch('price') 实时显示底层存储值。
组件 Token #
通过 ConfigProvider theme.components.Form 设置组件 Token;当前配置会同步作用于 Form 和独立 Form.Item,配置替换或撤除后也会更新。示例共用一份配置展示 vertical 与 inline 布局。需要局部覆盖时仍可在 Form 或 Form.Item 的原生 style 中设置 --apollo-form-* CSS 变量。
表单方法调用 #
通过 useForm() 取得表单实例后,可以调用 setFieldsValue、getFieldsValue、validateFields、validateFields({ validateOnly: true }) 与 resetFields。validateFields 校验失败时会 reject,示例捕获 errorFields 并把结果显示在页面上;validateOnly 只执行校验,不返回字段值。
render-props 使默认作用域插槽的 { values, form } 随 store 更新;示例直接显示当前 values,使用外部 useForm() 实例时也会更新。
动态表单项 #
useWatch('accountType', form) 监听账号类型,配合 v-if 动态渲染「公司名称」字段。Form.Item 的 rules 只在该字段实际存在时参与校验;切换类型后,已隐藏字段的值不会阻止表单提交。
动态增减表单项 #
Form.List 的默认插槽接收 { fields, operations, meta }:fields 用于 v-for 渲染行,operations.add / operations.remove / operations.move 负责增删与排序,meta.errors 汇总列表级校验错误。行内 Form.Item 使用 [field.name, 'name'] 这样的数组 name 与列表项绑定。
动态校验规则 #
rules 可以是 computed 计算出的数组。示例用 Switch 切换「普通 / 严格」模式:严格模式追加最小长度与「字母 + 数字」正则规则,Form.Item 会在下一次校验时立即使用新规则。Switch 带 aria-label,保证可访问名称。
表单上下文 #
在 Form 的后代组件中调用 useWatch('username') 时无需显式传入 form 实例:useWatch 会通过 Form 提供的上下文字段自动订阅。示例中的 WatchDisplay 是一个独立子组件,用来证明「不传 form 也能读到最新值」。
弹窗表单 #
把 Form 放进 Modal,在 @ok 中调用 form.validateFields():校验通过后关闭弹窗并展示提交结果,校验失败则保持弹窗打开,由 Form.Item 显示错误。Modal 的 closable 传入带 aria-label 的对象,保证关闭按钮有可访问名称。
嵌套路径 #
Form.Item 的 name 支持数组路径,例如 ['user', 'name'] 与 ['user', 'email'],它们会映射到 { user: { name, email } }。useWatch(['user', 'name'], form) 订阅嵌套值,setFieldsValue({ user: { ... } }) 可以一次写入整棵子树。
标签换行 #
Form 的 label-wrap 控制水平布局下标签是否允许换行;配合 label-col / wrapper-col 的栅格比例,可以处理超长标签。示例用 Switch 实时切换 label-wrap,并在页面中显示当前状态。
多种布局 #
同一页面可以并列多个 Form,分别设置 layout="inline"、layout="horizontal" 与 layout="vertical"。水平布局使用 label-col / wrapper-col 控制标签与控件的栅格占比;各表单拥有独立的内部 store,字段名互不影响。
登录表单 #
一个完整的登录场景:Form.Item 的 rules 校验用户名与密码,Checkbox 通过 value-prop-name="checked" 与布尔字段绑定,提交后由 @finish 展示欢迎信息。Input 使用 autocomplete 与 aria-label 兼顾浏览器自动填充与可访问性。
嵌套校验消息 #
Form 的 validate-messages 支持按规则类型嵌套覆盖默认文案:required、types.email、string.min、number.min 分别对应不同校验失败场景。模板变量如 ${name}、${min} 会在运行时替换为字段名和规则参数。
必填标记 #
Form 的 required-mark 接受 true、false 或 'optional'。自定义内容使用 #requiredMark="{ label, required }",其中 label 是保留原标签内容的稳定组件,可用 <component :is="label" /> 渲染。示例可实时切换默认标记、隐藏、optional 与自定义插槽。
语义化结构样式 #
通过 Form 的 classNames 与 styles 可以分别定制 root / label / content / help / helpItem / extra 六个语义槽。示例同时演示 Form.Item 的 help 与 extra,并用全局样式类覆盖 label 颜色、内容区背景、帮助文字与补充说明。
表单变体 #
Form 的 variant 会向下传导给输入控件,可选 outlined、borderless、filled、underlined。示例用 RadioGroup 切换变体,Input 与 Select 会同步更新视觉样式。
仅警告校验 #
在规则上设置 warningOnly: true 后,校验失败只会进入 meta.warnings 并展示警告,不会阻止 @finish。示例把「用户名」设为普通必填规则、把「昵称」设为仅警告规则,提交后可观察到两者对提交结果的差异。
无表单实例 #
不调用 useForm() 时,Form 会自动创建一个内部 store,Form.Item 的注入与 @finish 仍然正常工作。示例通过改变 key 重新挂载表单来实现重置,并展示 @finish 收集到的字段值。
basic #
最基础的表单:Form.Item 包裹控件,rules 声明校验。\n
customized-form-controls #
内联表单与提交按钮(html-type="submit")。\n
label #
label 定制:required 标记 / optional 文案 / 无 label(control 顶格)/ 无冒号 / tooltip。\n
layout #
三种布局:horizontal / vertical / inline。\n
validate-status #
校验状态(validateStatus + hasFeedback):错误/警告/校验中。\n
API
FormProps
| 参数 | 说明 | 类型 | 默认值 |
|---|---|---|---|
| form | 表单实例(useForm() 创建) |
FormInstance | - |
| name | 表单名(fieldId 前缀 + FormProvider 注册键) | string | - |
| layout | 布局 | 'horizontal' | 'vertical' | 'inline' | 'horizontal' |
| labelCol / wrapperCol | label / 控件列宽(grid ColProps) | ColProps | - |
| labelAlign | label 对齐 | 'left' | 'right' | 'right' |
| labelWrap | label 换行 | boolean | - |
| colon | 冒号(vertical 布局无效) | boolean | - |
| requiredMark | 必填标记;自定义内容使用 requiredMark 插槽 | boolean | 'optional' | true |
| initialValues | 初值 | object | - |
| validateMessages | 校验文案模板 | ValidateMessages | - |
| validateTrigger | 触发校验的事件 | string | string[] | false | 'onChange' |
| preserve | 字段卸载后保留值 | boolean | true |
| clearOnDestroy | 表单卸载时清除值 | boolean | false |
| fields | 受控字段值及状态;数组替换和字段内更新都会同步 | FieldData[] | - |
| disabled | 整表禁用 | boolean | - |
| size / variant / tooltip | 表单态与标签提示配置 | - | - |
| scrollToFirstError | 校验失败滚动到首个错误字段 | boolean | ScrollOptions | - |
| component | 容器元素(false 不渲染) | string | Component | false | 'form' |
| renderProps | 让默认槽的 values 随 store 更新;字段仍处理自身状态与重置 | boolean | false |
| classNames / styles | 语义槽(root/label/content/help/helpItem/extra)。⚠️ 也接受函数形态((info) => …);根槽与 ConfigProvider components.form 及调用方原生 class / style 合并(原生 style 胜) |
object | function | - |
事件(Emits)
finish(values) / finishFailed(errorInfo) / valuesChange(changed, all) / fieldsChange(changed, all);update:* 不适用(值由 store 管理)。
默认作用域插槽为 { values, form }。例如 <Form render-props v-slot="{ values }">…</Form>;普通字段表单可省略 render-props,字段继续独立订阅。
内容槽:requiredMark({ label, required }) 与 feedbackIcon({ status, errors, warnings })。label 是保留原始标签内容的稳定组件,模板中使用 <component :is="label" />。Form.Item 的同名 feedbackIcon 槽优先于 Form 槽;槽撤除后立即恢复当前默认内容。
FormInstance(expose)
getFieldValue / getFieldsValue / setFieldValue / setFieldsValue / resetFields / validateFields / submit / getFieldsError / getFieldError / getFieldWarning / isFieldsTouched / isFieldTouched / isFieldValidating / isFieldsValidating / setFields / getFieldInstance(name) / scrollToField(name, options) / focusField(name) / nativeElement。
getFieldInstance 返回已挂载控件的真实 DOM 或 Vue 公开引用对象(object | undefined),保持调用方模板 ref 的身份;不能假定每个自定义 expose 都有 focus 方法。focusField 在实际支持的能力上聚焦,scrollToField 使用真实控件元素,{ focus: true } 可同时聚焦。nativeElement 是实际 HTML 容器,无容器时为 null。
Form.Item
props:name(NamePath)、rules、dependencies、trigger、valuePropName、getValueFromEvent、getValueProps、normalize、validateTrigger、validateFirst、preserve、initialValue、messageVariables、shouldUpdate;展示:label / labelCol / wrapperCol / colon / required / tooltip / noStyle / help / extra / hasFeedback(boolean)/ validateStatus / hidden / htmlFor / layout。
slots:default({ control, meta, form })(子控件;有 name 时单个控件被注入 value 与事件)、label / help / extra / tooltip / feedbackIcon({ status, errors, warnings })。内容槽优先于对应 prop,显式空槽不会回退到 prop。无字段的布局项也提供同一对象,control 为空、meta 为当前空状态;脱离 Form 的布局项 form 为 undefined。
Form 与有布局壳的 Form.Item 将原生 class/style、属性和监听器落到各自实际根元素。noStyle 项与 Form.List 没有 DOM 根。labelCol/wrapperCol 使用 Grid ColProps 并可携带原生 class/style,嵌套布局项不会继承外层列宽。
事件:reset() / metaChange(meta),分别使用 @reset / @meta-change。组件不手动调用同名回调 Prop。
动态 prefixCls 与布局变更会更新派生类、真实控件的反馈图标、错误/帮助内容,并按已加载 CSS 重新测量 margin 占位。Form.ErrorList 独立使用时读取 ConfigProvider 前缀;在 Form.Item / Form.List 中使用最近的前缀上下文。动态前缀需要预先提供对应的静态 CSS,组件不会生成运行时样式。
Form.List
props:name。scoped slot { fields, operations, meta } —— fields: { name, key, fieldKey }[]、operations: { add, remove, move }、meta: { errors, warnings }。Form.ErrorList 用于展示 List 级错误。
Form.ErrorList 接受 help/errors/warnings 与原生根属性,visibleChanged(visible: boolean) 是所属事件。重复消息保留独立行,离场行使用最后收到的内容,结束后释放布局占位;不再从已经移除的当前 keys 反查消息。
useWatch
useWatch(dependencies, form) 或 useWatch(dependencies, { form, preserve }) —— 返回监听字段路径/selector 的 Ref,随调用它的 effect scope 释放。
useFormInstance() 读取最近 Form 的现有实例;Form 外返回 undefined,不创建新 store。重复 useForm(form) 与直接传给 Form 的同一外建实例共用控件注册表。
开发版直接把 Form / Form.Item 的旧位置参数槽迁为具名对象;requiredMark 内容函数、feedbackIcons 与 hasFeedback.icons 改用上述内容槽,不提供兼容层或弃用期。Form.List 既有对象作用域保持不变。校验器、取值/归一算法与异步业务回调仍是函数。
主题变量
11 个(labelRequiredMarkColor / labelColor / labelFontSize / labelHeight / verticalLabelHeight / labelColonMarginInlineStart / labelColonMarginInlineEnd / itemMarginBottom / verticalLabelPadding / verticalLabelMargin / inlineItemMarginBottom)。
使用 ConfigProvider theme.components.Form 配置,支持当前主题/组件 Token 替换与撤除,并作用于独立 Form.Item。长度数值会转换为 px;verticalLabelHeight 也接受 'auto'。原生 style 中的 --apollo-form-* 变量保留局部覆盖优先级,自定义前缀使用对应的变量前缀。