vue2 jsx二次封装el-form

143 阅读5分钟

我们在日常工作中经常遇到多数据的表单,写起来非常浪费时间+精力,市面上其他方法二次封装的el-form也是很棒的,这里我分享一下我自己写的封装方法

1.首先proform组件

<template>
  <div class="wapper">
    <ProForm
      ref="form"
      form-ref="freeForm"
      :model="formData"
      v-bind="formConfig"
      :rules="rules"
    />
  </div>
</template>

<script>
import { ProForm, DetailFormModal } from '@ajh/pro'

export default {
  components: {
    ProForm,
  },
  data() {
    return {
      // 表单数据console
      formData: {
        username: "",
        number: 0,
        time: "",
        orgIdProduction: "",
        sex: "",
        love: [],
        developmentMethods: "",
      },
      // el-form-item 配置项
      formConfig: {
        // labelWidth: 100, // 标题宽度
        labelPosition: "left",
        gutter: 12,
        schemas: [
          {
            required: true,
            label: "用户名",
            field: "username",
            component: "Input", // el-input可以省略,默认使用el-input
            placeholder: "请输入用户名", // placeholder可以省略,默认显示“请输入+label”
            span: 6, // 使用栅格布局
          },
          {
            label: "数字输入",
            field: "number",
            component: "InputNumber",
            controlsPosition: "right",
            span: 6, // 使用栅格布局
          },
          {
            label: "所属单位",
            labelWidth: 180, // 标题宽度-优先级高
            component: "Select",
            field: "orgIdProduction",
            span: 6,
            componentProps: {
              multiple: true, // 是否多选
              clearable: true, // 能否清空
              placeholder: "请选择",
              options: [
                {
                  label: "白庄煤矿",
                  value: "01076430",
                },
                {
                  label: "梁宝寺煤矿",
                  value: "01076323",
                },
              ],
            },
            onChange: (value) => {
              console.log(value);
            },
          },

          {
            label: "日期选择",
            field: "time",
            component: "DatePicker",
            type: "datetime",
            span: 6,
            componentProps: {
              width: "100%",
            },
          },
          {
            label: "性别",
            field: "sex",
            span: 6, // 支持栅格布局
            component: "RadioGroup", // 可以传入任意组件
            componentProps: {
              options: [
                {
                  label: "男",
                  value: 1,
                },
                {
                  label: "女",
                  value: 2,
                },
              ],
            },
            onChange: (e) => {
              console.log(e);
            },
          },
          {
            label: "菜单",
            field: "developmentMethods",
            span: 6,
            component: "RadioGroup",
            componentProps: {
              options: [
                {
                  label: "菜单1",
                  value: "menu1",
                },
                {
                  label: "菜单二",
                  value: "menu2",
                },
              ],
              onChange: (e) => {
                console.log(e);
              },
            },
          },
          {
            label: "兴趣爱好",
            field: "love",
            span: 6, // 支持栅格布局
            component: "CheckboxGroup", // 可以传入任意组件
            componentProps: {
              options: [
                {
                  label: "读书",
                  value: 1,
                },
                {
                  label: '菜单二',
                  value: 'menu2'
                }
              ]

            }
          }
        ]
      },
      addFormConfig: {
        labelWidth: 100, // 标题宽度
        labelPosition: 'left',
        gutter: 12,
        schemas: [
          {
            label: '用户名',
            field: 'username',
            component: 'Input', // el-input可以省略,默认使用el-input
            placeholder: '请输入用户名' // placeholder可以省略,默认显示“请输入+label”
          },
          {
            label: '数字输入',
            field: 'number',
            component: 'InputNumber',
            controlsPosition: 'right'
          },
          {
            label: '所属单位',
            labelWidth: 180, // 标题宽度-优先级高
            component: 'Select',
            field: 'orgIdProduction',
            componentProps: {
              multiple: true, // 是否多选
              placeholder: '请选择',
              options: [
                {
                  label: '白庄煤矿',
                  value: '01076430'
                },
                {
                  label: '梁宝寺煤矿',
                  value: '01076323'
                }
              ]
            },
            onChange: (value) => {
              console.log(value)
            }
          },

          {
            label: '日期选择',
            field: 'time',
            component: 'DatePicker',
            type: 'datetime',
            componentProps: {
              width: '100%'
            }
          },
          {
            label: '性别',
            field: 'sex',
            component: 'RadioGroup', // 可以传入任意组件
            componentProps: {
              options: [
                {
                  label: '男',
                  value: 1
                },
                {
                  label: '女',
                  value: 2
                }
              ]
            },
            onChange: (e) => {
              console.log(e)
            }
          },
          {
            label: '兴趣爱好',
            field: 'love',
            component: 'CheckboxGroup', // 可以传入任意组件
            componentProps: {
              options: [
                {
                  label: '读书',
                  value: 1
                },
                {
                  label: '写字',
                  value: 2
                },
                {
                  label: '听歌',
                  value: 4
                }
              ]
            },
            onChange: (e) => {
              console.log(e)
            }
          },
          {
            label: '菜单',
            field: 'developmentMethods',
            component: 'RadioGroup',
            isButton: true,
            clearable: true,
            hidden: true,
            componentProps: {
              options: [
                {
                  label: '菜单1',
                  value: 'menu1'
                },
                {
                  label: '菜单二',
                  value: 'menu2'
                }
              ]

            }
          }
        ]
      },
      // el-form-item 验证规则
    };
  },
  methods: {
    // 级联类型
    changeMajor(type) {
      const json = {
        primary: [
          {
            label: "数学",
            value: 1,
          },
          {
            label: "语文",
            value: 2,
          },
        ],
        junior: [
          {
            label: "英语",
            value: 5,
          },
          {
            label: '生物',
            value: 7
          }
        ]
      }
    },
    openAddFormModal() {
      DetailFormModal.show({
        title: '新增数据',
        schemas: this.addFormConfig.schemas,
        formData: this.formData
      }).then(res => {
        console.log('openAddFormModal', res)
      })
    }
  }
}
</script>

<style>
.wapper {
  background: #fff;
}
</style>

2.其他的二次封装组件包

<script lang="jsx">
import { Select, Option } from 'element-ui'

export default {
  props: {
    value: [String, Array],
    options: {
      type: Array,
      default: () => []
    },
    multiple: {
      type:Boolean
    }

  },
  data() {
    return {}
  },
  computed: {
    model: {
      get() {
        return this.value
      },
      set(newVal) {
        this.$emit('input', newVal)
      }
    }
  },
  render(h) {
    const { model, options, multiple} = this
    return (
      <Select vModel={this.model} clearable multiple={multiple}>
        {options.map((item) => {
          return <Option label={item.label} value={item.value}></Option>
        })}
      </Select>
    )
  }
}
</script>

<script lang="jsx">

import { CheckboxGroup, Checkbox } from 'element-ui'

export default {
  props: {
    value: Array,
    options: {
      type: Array,
      default: () => []
    }
  },
  data() {
    return {
    }
  },
  computed: {
    model: {
      get() {
        return this.value
      },
      set(newVal) {
        this.$emit('input', newVal)
      }
    }
  },
  render(h) {
    const { model, options } = this
    return (
      <CheckboxGroup vModel={this.model}>
        {
          options.map(item => {
            return (
              <Checkbox label={item.label} value={item.value}>
                {item.label}
              </Checkbox>
            )
          })
        }

      </CheckboxGroup>
    )
  }
}
</script>

<script lang="jsx">
import { Radio, RadioGroup} from 'element-ui'
export default {
  props: {
    value: [String, Array],
    options: {
      type: Array,
      default: () => []
    }
  },
  data() {
    return {}
  },
  computed: {
    model: {
      get() {
        return this.value
      },
      set(newVal) {
        this.$emit('input', newVal)
      }
    }
  },
  render(h) {
    const { model, options } = this
    return (
      <RadioGroup vModel={this.model}>
        {options.map((item) => {
          return <Radio label={item.label} value={item.value}></Radio>
        })}
      </RadioGroup>
    )
  }
}

</script>

3.然后引用子组件传入json配置项

<template>
  <div class="wapper">
    <ProForm
      ref="form"
      form-ref="freeForm"
      :model="formData"
      v-bind="formConfig"
      :rules="rules"
    />
  </div>
</template>

<script>
import { ProForm } from './ProForm'

export default {
  components: {
    ProForm,
  },
  data() {
    return {
      // 表单数据console
      formData: {
        username: "",
        number: 0,
        time: "",
        orgIdProduction: "",
        sex: "",
        love: [],
        developmentMethods: "",
      },
      // el-form-item 配置项
      formConfig: {
        // labelWidth: 100, // 标题宽度
        labelPosition: "left",
        gutter: 12,
        schemas: [
          {
            required: true,
            label: "用户名",
            field: "username",
            component: "Input", // el-input可以省略,默认使用el-input
            placeholder: "请输入用户名", // placeholder可以省略,默认显示“请输入+label”
            span: 6, // 使用栅格布局
          },
          {
            label: "数字输入",
            field: "number",
            component: "InputNumber",
            controlsPosition: "right",
            span: 6, // 使用栅格布局
          },
          {
            label: "所属单位",
            labelWidth: 180, // 标题宽度-优先级高
            component: "Select",
            field: "orgIdProduction",
            span: 6,
            componentProps: {
              multiple: true, // 是否多选
              clearable: true, // 能否清空
              placeholder: "请选择",
              options: [
                {
                  label: "白庄煤矿",
                  value: "01076430",
                },
                {
                  label: "梁宝寺煤矿",
                  value: "01076323",
                },
              ],
            },
            onChange: (value) => {
              console.log(value);
            },
          },

          {
            label: "日期选择",
            field: "time",
            component: "DatePicker",
            type: "datetime",
            span: 6,
            componentProps: {
              width: "100%",
            },
          },
          {
            label: "性别",
            field: "sex",
            span: 6, // 支持栅格布局
            component: "RadioGroup", // 可以传入任意组件
            componentProps: {
              options: [
                {
                  label: "男",
                  value: 1,
                },
                {
                  label: "女",
                  value: 2,
                },
              ],
            },
            onChange: (e) => {
              console.log(e);
            },
          },
          {
            label: "菜单",
            field: "developmentMethods",
            span: 6,
            component: "RadioGroup",
            componentProps: {
              options: [
                {
                  label: "菜单1",
                  value: "menu1",
                },
                {
                  label: "菜单二",
                  value: "menu2",
                },
              ],
              onChange: (e) => {
                console.log(e);
              },
            },
          },
          {
            label: "兴趣爱好",
            field: "love",
            span: 6, // 支持栅格布局
            component: "CheckboxGroup", // 可以传入任意组件
            componentProps: {
              options: [
                {
                  label: "读书",
                  value: 1,
                },
                {
                  label: '菜单二',
                  value: 'menu2'
                }
              ]

            }
          }
        ]
      },
      addFormConfig: {
        labelWidth: 100, // 标题宽度
        labelPosition: 'left',
        gutter: 12,
        schemas: [
          {
            label: '用户名',
            field: 'username',
            component: 'Input', // el-input可以省略,默认使用el-input
            placeholder: '请输入用户名' // placeholder可以省略,默认显示“请输入+label”
          },
          {
            label: '数字输入',
            field: 'number',
            component: 'InputNumber',
            controlsPosition: 'right'
          },
          {
            label: '所属单位',
            labelWidth: 180, // 标题宽度-优先级高
            component: 'Select',
            field: 'orgIdProduction',
            componentProps: {
              multiple: true, // 是否多选
              placeholder: '请选择',
              options: [
                {
                  label: '白庄煤矿',
                  value: '01076430'
                },
                {
                  label: '梁宝寺煤矿',
                  value: '01076323'
                }
              ]
            },
            onChange: (value) => {
              console.log(value)
            }
          },

          {
            label: '日期选择',
            field: 'time',
            component: 'DatePicker',
            type: 'datetime',
            componentProps: {
              width: '100%'
            }
          },
          {
            label: '性别',
            field: 'sex',
            component: 'RadioGroup', // 可以传入任意组件
            componentProps: {
              options: [
                {
                  label: '男',
                  value: 1
                },
                {
                  label: '女',
                  value: 2
                }
              ]
            },
            onChange: (e) => {
              console.log(e)
            }
          },
          {
            label: '兴趣爱好',
            field: 'love',
            component: 'CheckboxGroup', // 可以传入任意组件
            componentProps: {
              options: [
                {
                  label: '读书',
                  value: 1
                },
                {
                  label: '写字',
                  value: 2
                },
                {
                  label: '听歌',
                  value: 4
                }
              ]
            },
            onChange: (e) => {
              console.log(e)
            }
          },
          {
            label: '菜单',
            field: 'developmentMethods',
            component: 'RadioGroup',
            isButton: true,
            clearable: true,
            hidden: true,
            componentProps: {
              options: [
                {
                  label: '菜单1',
                  value: 'menu1'
                },
                {
                  label: '菜单二',
                  value: 'menu2'
                }
              ]

            }
          }
        ]
      },
      // el-form-item 验证规则
    };
  },
  methods: {
    // 级联类型
    changeMajor(type) {
      const json = {
        primary: [
          {
            label: "数学",
            value: 1,
          },
          {
            label: "语文",
            value: 2,
          },
        ],
        junior: [
          {
            label: "英语",
            value: 5,
          },
          {
            label: '生物',
            value: 7
          }
        ]
      }
    },
    openAddFormModal() {
      DetailFormModal.show({
        title: '新增数据',
        schemas: this.addFormConfig.schemas,
        formData: this.formData
      }).then(res => {
        console.log('openAddFormModal', res)
      })
    }
  }
}
</script>

<style>
.wapper {
  background: #fff;
}
</style>

最后展示效果:

image.png

大致就是这样,vue2+jsx+element-ui的el-form,封装了一层components,遍历的时候传入json的component区分是input输入框还是其他输入框,特殊输入框进行二次封装(el-select,el-radio)