动态表单生成Demo(Vue+elment)

摘要:本文将介绍如何使用vue和elment ui组件库实现一个简单的动态表单生成的Demo。主要涉及两个.vue文件的书写,一个是动态表单生成的组件文件,一个是使用该动态表单生成的组件。

1.动态表单生成组件

这里仅集成了输入框、选择框、日期框三种类型的表单项;

其他类型的表单元素,比如单选框、复选框等,也可以根据需要进行类似的处理。

可以动态计算每一行放置的表单数。

<template>
  <div>
    <el-form :model="data" :rules="rules" :label-width="labelWidth" :disabled="formDisabled">
      <el-row :gutter="10" style="display: flex; flex-wrap: wrap">
        <template v-for="(field, index) in formFields">
          <el-col :key="index" :span="calculateSpanSize(field)">
            <el-form-item
              :prop="field.name"
              :label="field.label"
              :rules="field.rules"
              :require="field.require ? field.required() : false"
              v-bind="field.bind"
            >
              <el-input
                v-if="field.type === 'text'"
                :type="field.type"
                :id="field.name"
                :name="field.name"
                v-model="data[field.name]"
                :style="{ width: field.width || '100%' }"
              />
              <el-select
                v-else-if="field.type === 'select'"
                :id="field.name"
                v-model="data[field.name]"
                :style="{ width: field.width || '100%' }"
              >
                <el-option
                  v-for="(option, optionIndex) in field.options"
                  :key="optionIndex"
                  :value="option.value"
                  :label="option.label"
                  :style="{ width: field.width || '100%' }"
                >
                  {{ option.label }}
                </el-option>
              </el-select>
              <el-date-picker
                v-else-if="field.type === 'date'"
                v-model="data[field.name]"
                :type="field.type"
                placeholder="选择日期"
                :style="{ width: field.width || '100%' }"
              >
              </el-date-picker>
            </el-form-item>
          </el-col>
          <!-- 其他类型的表单元素,比如单选框、复选框等,也可以根据需要进行类似的处理 -->
        </template>
      </el-row>
      <el-row><el-button type="success" @click="submitForm">提交</el-button></el-row>
    </el-form>
  </div>
</template>

<script>
export default {
  name: 'MyFrom',
  props: {
    labelWidth: {
      type: String,
      default: '100px'
    },
    rules: {
      type: Object,
      default: () => {}
    },
    formFields: {
      type: Array,
      default: () => []
    },
    data: {
      type: Object,
      default: () => {}
    },
    spanSize: {
      type: Number,
      default: 2,
      validator: value => {
        return value <= 5
      }
    },
    disabled: {
      type: Boolean,
      default: false
    }
  },
  data() {
    return {}
  },
  created() {},
  computed: {
    formDisabled() {
      return typeof disabled === 'function' ? this.disabled() : this.disabled
    }
  },
  methods: {
    submitForm() {
      // 处理表单提交逻辑
      console.log('Form Data:', this.data)
      this.$parent.submintData(this.data)
    },
    calculateSpanSize(item) {
      const span = item.span || 1
      const spanTemp = (24 / this.spanSize) * span
      return spanTemp > 24 ? 24 : spanTemp
    }
  }
}
</script>

2.使用动态表单的父组件

1.引入动态表单生成组件

2.对表单的属性进行配置

3.点击按钮调用父组件的提交数据函数,打印表单提交数据,看数据是否绑定成功

<template>
  <div style="width: 800px">
    <my-form :form-fields="formFields" :data="formData" :span-size="2"></my-form>
  </div>
</template>

<script>
import MyForm from './MyForm.vue'

const defaultFormData = {
  name: '',
  gender: '',
  birthday: '',
  enabled: true,
  address: '',
  id: ''
}

export default {
  name: 'HelloWorld',
  components: { MyForm },
  props: {
    msg: String
  },
  data() {
    return {
      isEdit: false,
      visible: false,
      formFields: [
        {
          type: 'text',
          label: '姓名',
          name: 'name',
          rules: [{ required: true, trigger: 'blur', message: '请输入姓名' }],
        },
        {
          type: 'select',
          label: '性别',
          name: 'gender',
          options: [
            { label: '男', value: '1' },
            { label: '女', value: '0' }
          ]
        },
        { type: 'date', label: '生日', name: 'birthday' },
        {
          type: 'text',
          label: '家庭地址',
          name: 'address',
          rules: [{ required: true, trigger: 'blur', message: '请输入家庭地址' }],
        }
        // 可根据需要添加更多的表单字段
      ],
      formData: Object.assign({}, defaultFormData)
    }
  },
  methods: {
    submintData() {
      console.log('11111' + JSON.stringify(this.formData))
    }
  }
}
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped lang="scss">
h3 {
  margin: 40px 0 0;
}
ul {
  list-style-type: none;
  padding: 0;
}
li {
  display: inline-block;
  margin: 0 10px;
}
a {
  color: #42b983;
}
</style>

提交结果:

3.思考

1.在设计动态表单生成组件时,可以使用component标签改进,而不是为每一种类型的表单项都写一个if判断,毕竟表单项类型比较多;后期会对这个点进行改进;

2.提交按钮可以放到父组件,动态表单生成组件就只负责生成表单以及绑定数据等逻辑的操作。

3.当你在一个 el-row 中包含多个 el-col(列)时,你可以使用 gutter 属性来设置列之间的空隙,以增加页面的可读性和美观度。