Bootstrap

Vue3 Element-Plus 一站式生成动态表单

        经常开发管理系统的小伙伴们肯定或多或少都遇到过表单需求,对于一个系统而言,动辄就是十几,几十个表单;如果每个表单都按照传统模式编写的话,简直要把前端累死,看着一段段大同小异的代码,也是提不上一点劲,甚至看着这些它懂你,你不想懂它的代码就犯恶心。
本着偷懒的精神,我就想能否封装一个动态表单,实现思路大致就是通过JSON配置,动态生成表单页面,于是说干就干,咱玩的就是真实对吧。开撸,开撸.....

type TreeItem = {
  value: string
  label: string
  children?: TreeItem[]
}

export type FormListItem = {
  // 栅格占据的列数
  colSpan?: number 
  // 表单元素特有的属性
  props?: {  
    placeholder?: string
    defaultValue?: unknown // 绑定的默认值
    clearable?: boolean
    disabled?: boolean | ((data: { [key: string]: any }) => boolean)
    size?: 'large' | 'default' | 'small'
    group?: unknown // 父级特有属性,针对嵌套组件 Select、Checkbox、Radio
    child?: unknown // 子级特有属性,针对嵌套组件 Select、Checkbox、Radio
    [key: string]: unknown
  } 
  // 表单元素特有的插槽
  slots?: {  
    name: string
    content: unknown
  }[] 
  // 组件类型
  typeName?: 'input' | 'select' | 'date-picker' | 'time-picker' | 'switch' | 'checkbox' | 'checkbox-group' | 'checkbox-button' | 'radio-group' | 'radio-button' | 'input-number' | 'tree-select' | 'upload' | 'slider' 
  // 表单元素特有的样式
  styles?: {
    [key: string]: number | string
  } 
  // select options 替换字段
  replaceField?: { value: string; label: string } 
  // 列表项
  options?: {
    value?: string | number | boolean | object
    label?: string | number
    disabled?: ((data: { [key: string]: any }) => boolean) | boolean
    [key: string]: unknown
  }[]
  // <el-form-item> 独有属性,同 FormItem Attributes
  formItem: Partial<FormItemProps & { class: string }>
  // 嵌套<el-form-item>
  children?: FormListItem[]
  // 树形选择器数据
  treeData?: TreeItem[] // 只针对 'tree-select'组件
  // 组件显示条件
  isShow?: ((data: { [key: string]: any }) => boolean) | boolean
}

export type FConfig = {
  form: Partial<InstanceType<typeof ElForm>> // Form Attributes 与Element属性一致
  configs: FormListItem[]  // 表单主体配置
}
1.实现思路,提供一个isShow方法,将方法绑定在对应的组件上,从而组件显示隐藏条件

 isShow: (data = {}) => {
  return model.value.region == 'shanghai'
}
....
<el-form-item v-if="isShow(model)" v-bind="item.formItem">

 2.目标组件是否禁用,需要根据某个组件是否有值来判断

  • disabled: (data = {}) => {
  •     return !model.value.date1
    }
    ....
    <component :disabled="disabled(model)"></component>

3. 表单验证

formItem: {
  prop: 'name',
  label: 'Activity name',
  rules: [
    {
      required: true,
      message: 'Please enter content',
      trigger: 'blur'
    }
  ]
}
 

;