An open API service indexing awesome lists of open source software.

https://github.com/cbtpro/antdv-vue-admin


https://github.com/cbtpro/antdv-vue-admin

Last synced: about 2 months ago
JSON representation

Awesome Lists containing this project

README

          

#### title: 复杂表单的设计思想与实现方案

[TOC]

## 导读

本文旨在分享几种开发复杂表单的设计思想和实现方案,适用于 Vue 或 React 等前端框架中的中大型表单场景。本文覆盖了常见表单类型、步骤式流程、动态交互、数据校验等多个维度的设计与实现。如果你在项目中遇到未覆盖的情况,欢迎评论或私信交流,共同完善这份指南。

---

## 常见表单种类

### 简单表单

[一个简单的基础表单的Vue示例](https://play.vuejs.org/#eNq1VVtrE0EU/ivjvqSFmsXLg43b4IWK+qCigi/7sslO0q27M8vubGwJgVZbpWBoRFtQGqRYbAWxLdZLm1r/THaT/gvP7Gw220uqoRgI7JzvzDlnvnPmm7J01bbTJQ9LGUlx845hM+Ri5tlZlRiWTR2GysjBBVRBBYdaKAWuqRi6QR1rVDcYdSI0LXdNPGrqskpUkqfEZchyi2iExxpI3cSmSdEj6pj6mdSgShRZpIaksGDYsk2NYVghpCRyyGBR5AQsDUnMhegFo5gedymBQ5T5JlXKU8s2TOzctZkB2VUpg0KEYxokf3I7tDHHw0Mde34M5x8fYx93J7hNle452MVOCatSjDHNKWIm4NEHd/AEfMegRXXPBO8TwPvYpabHaxRu1zyiQ9kJv7DaWyHfBik+dEcnGCZu51C8UO5ZCf1VCTi/fsLRu+VeSF8M96mkAiwe7BqfhYNN0I1S+AGfY+ez7eU1v7rQ2l1s771SZDBEUAGioCuul7MMlrYdXMKEjaiSMPAUqhS5cmcDmzqMWmwBm4mLmOhZ//1Oa3mq+Xs5mF5X5MiYdNNy2EwYEPJXX/u1agYpBrE9hkpngV1sQm5eUppoFnQBsUkbg4mFfQiHKY4oHw55XI7trf29mcM50sSzctjppNKKiUwC+ksuRT7CxEnctNc/thrP++JmacOvT/XiRtN1mGqYktPS03rzrb1e75XGHqOkvx70yUsw98nfXOiLl9nP/vzPXgVzAdHI5Ol5aU+/bP7qOZo2dQ1x+/8fNf7s92ZjsS9qVl4EX9egZl6M5mDtyI2iDLqZ5WIsHPqsNucxRknnyEIgIF4wX2vurCiygGP3chmF0lIBtYoiwlIokyyk6cCzAMt/fcoS71OYQjxQ0SMidIPLsr+y6s9Xg629SJhBlvlFz6Dh4c66c49C96WNVu1Z7BsNP0fOXRo+F/1iOB61cOv0j1Z9qrldC5bm9t/W2lsfmo2GGNVuvHho+I6g/nR/czcGRWtE0byLqgQSP5g4Z1eO4bQDg2gkK94HjlITp01aHEiJTrTezQitDxY2guqXTGooZIlHq8A/8WxLlT9yf9dM)

[拆分模块后的次简单的 Vue 示例](https://play.vuejs.org/#eNrtV19vG0UQ/yrLvdiRwp0KPBBzsaAQRJGgFSB44Hg4+9bOlbvd092eSWVZSqAFVSKKEaQSKBGKiGgrVU2qpn/Tpl/Gd3a+RWd376/buE7UvsVPnp3fzuzM/GZ3rqt85HlqJ8RKTdGDpm97DAWYhV7dILbrUZ+hLvJxC/VQy6cuqgC0kqk+pb67YNmM+olW1fIlbrXygUEM0qQkYMgN2mie26pWPsOOQ9F31HestyozBtE16RqcgsCw6zkmwyAhpBd8aLCiawW1MquwAKy37LZ6MaAEgujyTYbSpK5nO9g/7zEbvBtKDQkN15ng/KfPxRrzQzybrjcXcfPHl6xfDJb4mqFc8HGA/Q42lEzHTL+NmVQvfP0lXoL/mdKlVugAeoLyKxxQJ+RnlLCzIbHg2AWcOO05kW+btL8JFpYYJkEaFD8oR/YE3lAg5x9PCD0/7rvqe2KfQXqQxbNmYDfPkRZNqVCuQcvGjgW0EBLIDm5jYtWjfx8Pt5YHz7bilR1dSxZTiNnATiIgFF3/M+qv1pBuEy9kqPM2RI+deUNxaNN0vuCCSkwXcoXYJQ+DgolsiZILe1rR4Lj1R3uHB5fHraskdBvYLzsx2wUfEnCEF10rRF1iHYhHdQqnXciwVWqXQg94PvUC6AILt2yCL3Cp+n1FHPdb0wHsDzOAlljs2iyDLoDAoaFnwSFq4zvSPXmksDM9TFWUH+peQ9UZNF+Xp1BzG4I7EAvoO1wWIO6++hJ/s0higDjcc6F1gUefYGbazrGJNNr5f7j/61RE2tiNNpcnE8m0LGhUIP5JuDT8695oZ3OyA2+RkumoekqiE5BI3HDWsUkUX70Z3VmfikRXbkVrDyfXmMdtkksnI9Fo5ffB01dcdx4NbHnvn/LozfDoPFvE/vEftSv3B/vXpqLR9m/x3RtQZV4408fmEe8aZXBZ1HnVJOy0vq+nvuVR88UCW3YnTfXiO/XR1o1odX345Nro4A9dg4VE1QIr6MMgbMARVM/HHUwYFFAucBdQu7TiejYnFUrNDagNrig0L2Dzt3AcbAlNGZ1feuNoYA1oyuiM2uNgyhVlbCNkjJL0kpFxQUzxWn/weFvXpDqDd7vcTg/mQslRLiUUlfmclp3jHw1QvkSXJzH9aCiNnwVkIYUptDxhFLCFBKbY8kNSwObpS6Glu6LYRIIe8rOlCwN0UmcYqUGQEysf26Pt69Haarx3AIM7n9n5lFlDc3Mwl4OY1lvuysYTsXFjd9j/Re5Kxgq+fOb9uTPJD4opjKQ0kEay50kYWXkw3FwePOrHG1cP/+6P9v4b7O/LRy6xnL01HB5v/nx450lqN2FMEpG4q2RE/HLjICRaL81H3heQFdnhouO5ljpYdWi7WpHcGv5zWTZdvL4br96uQTfzbHJrvbFm7j0HE3kkRw==)

[css美化后的表单](https://play.vuejs.org/#eNrtWFuPGzUU/itWKpQUJZNltxJoSC8UFqmVaKu24oXw4J3xJG499sj2bHeJIrVSC0KiahG0D4gKVaqgSIgWcRG0UP7M3vgXHNszE2ez2Xbb3X3a5GXs8/n4nOPz+XIGtXeyLFjMSS2sdVQkaaaRIjrPjnU5TTMhNRogSRI0RIkUKaoDtF6J3hcynY+pFrKQBu1Rl9Faf7vLuzwSXGlEOdUUMwNAR9FgCCInSFwPzNIYBEHg4YaHAdRpO7vAImhokmYMawIthDqeAYutVMSEHe3WjL5uDbUdJKaLKGJYKZCQqC+6NduP0Mb9h6s376zdebx28+fBAJ2+cPZMoLSkvEeT5YZR0kQ8Z6yJZg+j4dAqa4M2GN5pe2ZAU+llZj5PFHHJJWvU+1pnKmy3c55d7gWRSNuSQGhbkVLuK4CvuvHwdTQw2iPBhAzRobm5OehEEBeuWwlOKVsOUf0iTYlCZ8gVdF6kmNebyPY0YbkkTWAAWBgYB52yDMcxuBKi2WzJaiu0SxI7LITVWl1r1rSChUhoL7ikBIdEsAq6NTA5o4zIs5mmsFDdWuhUGxlmTFw5bfu0zEmz7I/6JLq8Rf8ltWT6urVzxnW5SLq1Sqax7BHtxPMXzpAl+K6EsKg5A/Q2wvNECZYbGx3sZM5jMNvDWWtP2bWBmFxU80uacFU6ZQw1yKHFd2uQt+9u4/rI3LngiB0H8YQonsSKRqd4Iko6jadqQgmLYdWL7Osw0iM8rlJTEViDuKWpNt4WIICpDPMKpK37x1a/e7J+/+rKv/fXrj2CZQREqbTttFZz4AXCqtG25ev2qWGFrXKCH75avX0zrPJ9Kp7yLDcDSgiAbJfHRiYizD4wjYDjFHxDejkjlTMFTZ31o9nAEzOBpderufLXb/89u74LrgQ8TxeIHPcI9zyHHOAFXDLfXjpM7CZTtmHDx1yTeGwv9jbYTIpMwUYak4Rycs60Gh/VrfEfYgbYj81m47AkpbqCzkPDQPMsBiPCzSPKMSO/YWRpTMPyAggRosZhdPSYsyIY6bCkAl9AvmjaFmSmb2wxXxM5DDBq09YPBHuPaEzZvjBs49H3608/3UuGfft49d7VXWcYbPqwv8J+tUOSvZIv61//vvHo3q77kvUF3/l2ccCtl+KWPRHjfeHW2uc/rv5yZy+5deOn1Vt/7no+mlXBfHl/ubVx7YuVf3b/JM6Egku2uTAd0Gs/6HVW94ncn7vhjT9Wnt7dS3Y9+Gzt14cvl5FGBZYET7keCm3cMznlYAe5uBe5OP5Cn0xGL9T+ok5kX3924tZkX9Trf9/dePZlp92frVbMU2kf+ydUvgCmB5kki4Rrk+K2w5jmT1E9qaa97i1qdC/cFjY64raFVVTdFrWQay14uXk6683Zduv2ypMHnbYTV/6b8UXCTikgPCdXm36KNScKMrDGxZBRxMqCzNiz1EN6USuh4xdsD+uFrsSOXxg87Ch+JXRs83tZphVFoql8KZ7nEiIo+QR70PHjruJUvvI3M6kYbgiltmeU02B55e8CIz+esw24IaN8h3GeB0YqGAmY6DXqLpvWv7nul6pCsMUEw+gyHo2Xx8pKVGDp6nTGVEGqQQ0pYcTVgjCjPd6ikIMqRBEwkEjbf4XGuh+iN2ZmXrPtPqG9PgRqriwiTRu4IGRMZEvimOYgOVLAXTcozJYQuEVjdIi8af5OiqPLPSmgWgNFL5KYv+0PzHZSrkhRx2oxkoAhpeLJYtmOy2XVEEU/IWDiW4VqU80xoQz8U3engdza6iqcM0XHmKelRzPY/D1bAndU79AEUJenvNXDWYhK3ybW06m2R/vWAfeiUqHdvbKAFykzO1P6hKDQC/Ki9lad+AV8MsfMr0gfLcBWDq++zQJny1YS6RzaSrQgYA9OXfLFWPXhxPezr7SuFcM6S2xuwyGCXCSSAYkLiHXbrUJZL4UzdPg/34Pntw==)

表单字段简单,没有复杂的组件和逻辑,样式也不复杂。

### 步骤式表单(Steps / Wizard Form)

一种将表单拆分为多个步骤、逐步引导用户填写的交互模式,常见于注册流程、信息采集、向导配置等场景。

特点:

- 分步骤进行,避免信息过载
- 用户体验友好,引导式填写
- 可视化进度提示
- 支持阶段性校验与保存
- 适合复杂或冗长表单场景

缺点:

- 逻辑跳转增加实现复杂度
- 状态管理需统一处理
- 表单校验要支持分步与整体校验
- 对代码整体掌握要求较高

代码编写时注意表单字段和界面交互代码尽量分割,各司其职。

---

### 分段表单(Segmented Form)

按模块拆分表单,支持任意顺序填写。

应用场景:

- 表单结构较大但逻辑不强依赖
- 后台管理系统中的“基础信息 / 配置 / 权限设置”等模块

技术实现:

- 使用 Tabs、Collapse、Card 等 UI 组件
- 每段独立处理校验与绑定
- 最终统一提交或按段保存

---

### 嵌套表单(Nested Form)

一个表单项中嵌套另一个表单或多组字段,适合以下情况:

- 结构复杂的字段组
- 重复子项(如多个联系人)
- 嵌套组件自带表单逻辑(如上传、地图选择)

技术要点:

- 使用 `v-model:value` 实现双向绑定
- 自定义组件暴露 `validate()`、`reset()` 方法
- 父级统一处理状态与校验

---

### 表格表单(Table Form)

用于批量编辑或录入多条数据记录。

特点:

- 每行代表一个表单实体
- 支持动态增删、复制、拖拽排序
- 表格列支持自定义表单控件

示例结构:

```vue



{{ record[column.dataIndex] }}

```

---

### 动态表单(Dynamic Form)

字段会根据条件动态增减或变化。

常见功能:

- 条件字段显示 / 隐藏
- 联级选择(如省市区)
- 表单项动态添加 / 删除
- 联动校验、输入联动

技术建议:

- 用配置驱动生成字段(JSON Schema 或 DSL)
- 拆解为复用组件,结合事件驱动模型

---

## 布局

### 布局方式

- antdv提供了Divider、Grid、Layout、Space.
- Form表单提供了layout属性'horizontal'|'vertical'|'inline',labelAlign属性'left'|'right',labelCol属性,wrapperCol属性,labelWrap属性来确定标签的文本换行方式.
- 使用css来实现复杂布局
- 风格、布局样式分离

- 尽量不要直接在组件上应用布局样式,布局样式在外层套用一个div用来处理布局样式。
- antdv的form组件提供了noStyle属性,如果为true,则不使用antdv的样式,表单作为纯字段控件使用。

## 响应式绑定和ref访问

## 表单校验实践

下面以 Ant Design Vue 为例

场景:禁用字段参与\不参与校验,这种设计允许开发者根据业务需求动态控制字段的验证行为。

- 动态计算 rules

```ts
const getUsernameRules = computed(() => {
return isDisabled.value
? []
: [
{ required: true, message: '请输入用户名', validateTrigger: 'change' },
{ min: 3, message: '用户名至少 3 个字符', validateTrigger: 'change' },
];
});
```

- watch 动态切换规则

```ts
watch(isDisabled, (val) => {
rules.username = val ? [] : [{ required: true, message: '请输入用户名', validateTrigger: 'change' }];
});
```

只手动校验部分字段

```ts
formRef.value.validate(['username', 'password']);
```

- 使用 required 动态控制是否校验

​ 在许多表单验证库(如 VeeValidate、Vuelidate、Ant Design Vue 、async-validator、yup等)中,验证规则通常遵循以下逻辑:

​ - 当字段未被标记为必填(即 `required: false`)且值为空时,验证器会跳过其他规则的验证。

​ - 只有当字段被标记为必填(没有显式的required: false,即 `required: true`)时,验证器才会在字段为空时触发错误提示。

```vue

```

```ts
const isEmailRequired = computed(() => form.notifyByEmail);
```
- 自定义 validator 控制校验逻辑

```ts
{
validator: (rule, value) => {
if (isDisabled.value) return Promise.resolve();
if (!value) return Promise.reject('请输入用户名');
return Promise.resolve();
};
}
```

---

## 表单校验注意事项

复杂表单的校验不仅涉及规则本身,还涉及动态控制、状态依赖、交互设计等多种维度。

---

💡 Tip:避免重复的规则项导致重复提示

当 `rules` 数组中存在多个相同类型的规则(如多个 `required`),即使错误信息不同,也会导致校验失败时**重复弹出多个错误提示**:

```ts
rules.username = [
{ required: true, message: '请输入用户名' },
{ required: true, message: '该字段不能为空' }, // ⚠️ 冗余
];
```

建议:

- 避免在组件合并、扩展、拼接规则时重复添加同类规则。
- 规则配置建议用函数返回,统一校验逻辑。

---

## 实战建议与技巧

- 表单重置:推荐 `form.resetFields()`,动态字段需注意初始化。
- 文件上传组件:封装通用组件,统一参数、格式与交互。
- 联合校验:使用 `validator` 实现字段间联动校验。
- 性能优化:懒加载/虚拟滚动表单项,减少初始渲染负担。
- 状态管理:推荐用 Vue 的 `reactive` / `pinia`、React 的 `Zustand`、`useReducer` 管理复杂状态。
- 数据持久化:使用 `localStorage` 或后端草稿接口保存中间态。

---

## 结语

表单是前端开发中最常见但也最容易“踩坑”的模块,尤其在中大型项目中,随着交互需求的复杂化,表单系统的设计愈加重要。希望本文能为你在构建复杂表单时提供参考和启发。