12、表单系统设计:动态表单 + 校验 + 可配置化

🪜 写在前面

表单,是前端系统最基础但最复杂的模块之一。 它常常包含:

  • 大量字段、交互逻辑、联动控制
  • 多种校验规则、字段显示控制、动态字段生成
  • 提交、校验、重置、草稿保存、只读模式等状态管理
  • 表单配置平台化(低代码配置出页面)

本篇我们将一步步实现一套通用、动态、可扩展的表单系统,覆盖以下能力:

✅ 表单字段动态渲染

✅ 多类型字段支持(输入框/下拉/日期/开关/上传等)

✅ 校验规则可配置

✅ 字段联动控制(显示/禁用/值变化)

✅ 表单模式(编辑/只读)切换

✅ 支持后续平台化配置表单模板


🧱 一、表单渲染核心设计思想

用 JSON Schema + 渲染组件映射 实现动态表单:

ts 复制代码
export interface FormSchema {
  label: string
  field: string
  type: 'input' | 'select' | 'switch' | 'date' | 'upload'
  required?: boolean
  options?: Array<{ label: string; value: any }>
  defaultValue?: any
  rules?: Array<any>
  showWhen?: (formModel) => boolean
  disabledWhen?: (formModel) => boolean
}

📦 二、核心目录结构设计

bash 复制代码
components/
├── DynamicForm.vue         # 主表单组件
├── fields/                 # 各类型组件
│   ├── InputField.vue
│   ├── SelectField.vue
│   ├── SwitchField.vue
│   └── ...
hooks/
├── useFormRender.ts        # 渲染逻辑封装
├── useFormModel.ts         # 状态管理封装

✅ 三、基础组件结构(DynamicForm)

vue 复制代码
<!-- DynamicForm.vue -->
<template>
  <Form ref="formRef" :model="formModel" :rules="rules">
    <FormItem
      v-for="schema in visibleSchemas"
      :label="schema.label"
      :prop="schema.field"
    >
      <component
        :is="getFieldComponent(schema.type)"
        v-model="formModel[schema.field]"
        v-bind="getFieldProps(schema)"
        :disabled="isDisabled(schema)"
      />
    </FormItem>
  </Form>
</template>
ts 复制代码
// 渲染辅助逻辑
function getFieldComponent(type: string) {
  return {
    input: InputField,
    select: SelectField,
    switch: SwitchField,
  }[type]
}

🧩 四、支持动态联动(showWhen、disabledWhen)

ts 复制代码
const visibleSchemas = computed(() =>
  props.schema.filter((schema) =>
    schema.showWhen ? schema.showWhen(formModel.value) : true
  )
)

function isDisabled(schema: FormSchema) {
  return schema.disabledWhen ? schema.disabledWhen(formModel.value) : false
}

配置示例:

ts 复制代码
{
  field: 'username',
  label: '用户名',
  type: 'input',
  required: true
},
{
  field: 'adminCode',
  label: '管理员编号',
  type: 'input',
  showWhen: (form) => form.role === 'admin'
}

🔐 五、校验规则支持

支持默认 + 自定义:

ts 复制代码
{
  field: 'email',
  label: '邮箱',
  type: 'input',
  rules: [
    { required: true, message: '请输入邮箱' },
    { type: 'email', message: '格式不正确' },
  ],
}

表单验证封装:

ts 复制代码
async function validate() {
  return formRef.value.validate()
}

🧲 六、只读模式/编辑模式统一处理

方式1:组件接收 readonly 属性控制渲染

vue 复制代码
<!-- InputField.vue -->
<template>
  <span v-if="readonly">{{ modelValue }}</span>
  <Input v-else v-model:value="modelValue" />
</template>

方式2:统一在 DynamicForm.vue 中处理

vue 复制代码
<component
  :is="getFieldComponent(schema.type)"
  v-model="formModel[schema.field]"
  :readonly="props.readonly"
  :disabled="props.readonly || isDisabled(schema)"
/>

📦 七、支持插槽 & 自定义组件注册

vue 复制代码
<FormItem v-if="schema.slot">
  <slot :name="schema.slot" :form="formModel" />
</FormItem>

允许使用:

vue 复制代码
<DynamicForm :schema="formSchema">
  <template #customSlot="{ form }">
    <Input v-model:value="form.customField" />
  </template>
</DynamicForm>

🎯 八、平台化配置建议(支持后台配置)

后端返回:

json 复制代码
[
  {
    "field": "username",
    "label": "用户名",
    "type": "input",
    "required": true
  },
  {
    "field": "role",
    "label": "角色",
    "type": "select",
    "options": [
      { "label": "管理员", "value": "admin" },
      { "label": "普通用户", "value": "user" }
    ]
  }
]

前端直接传入 schema,完成渲染。


🧠 九、性能优化建议

优化点 建议方案
schema 频繁变动 使用 v-memo 或 shallowReactive
只读表单渲染 使用只读组件(纯文本)+ 懒加载字段
联动过多 使用 computed 缓存联动状态
多类型组件动态渲染 使用缓存组件工厂 (defineAsyncComponent)

💡 十、组件封装建议(进阶)

类型 说明
DynamicForm.vue 渲染主组件
FormRender.ts 生成组件映射表,支持自定义注册
useForm.ts 暴露 validate/reset/setFields 等方法
useFormSchema.ts 拆分 schema 过滤/联动/权限逻辑
FieldWrapper.vue 可扩展插槽 + 错误提示包装器

🧠 总结一句话

表单系统的通用化设计,是支撑前端"配置化平台"、"低代码编辑器"的核心引擎。


下一篇我们进入高复用组件系统的核心场景:

👉 《表格系统架构:列配置、嵌套数据、复杂交互》

相关推荐
葡萄城技术团队7 小时前
1000 人协同压测的环境瓶颈排查:CPU 争用与 Wi\-Fi
前端
Shulex8 小时前
跨境电商 AI Agent 核心架构解析:从只读问答到自主执行的工程落地
人工智能·架构·智能客服·跨境电商
钱工的门窗技术笔记8 小时前
室内极窄全景移门的支承路径与预留接口:轨道形式、型材壁厚口径与验收边界
物联网·架构·数据分析
excel8 小时前
Marked 与 Markdown 有什么区别?该怎么选?
前端
码农小旋风8 小时前
Ray分布式计算引擎介绍
人工智能·架构
ZhengEnCi9 小时前
Agent 架构怎么选:从单 Agent 到多 Agent 编排的选型决策指南
算法·架构
星融元asterfusion9 小时前
工业网络升级实战:100G 双轨 Leaf-Spine 架构破解高并发出货网络瓶颈
网络·架构·spine
Da Da 泓9 小时前
五子棋 Web 端测试用例报告
前端·网络·websocket·网络协议·测试用例·项目
天远数科10 小时前
零信任架构实战:基于天远企业法人四要素高级版构建自动化供应商资质穿透核验网关
人工智能·架构·自动化
zxcvb15310 小时前
远程查看本地文档:一条轻量 Web 文件服务的工程化链路
前端·远程查看文档