form表单的三种封装方法(Vue+ElementUI)
- 1.首先是最普通,也是大家最先想到的方法,直接封装:
- 2.实现表单动态渲染、可视化配置的方法,动态表单又可以分为两种方法:(注意:注意 v-model 的绑定问题, 组件内不能直接修改props 。)
- 3. **动态生成表单**
1.首先是最普通,也是大家最先想到的方法,直接封装:
| <template> |
| <el-form |
| :inline="true" |
| :model="value" |
| label-position="right" |
| :label-width="formConfig.labelWidth" |
| :rules="rules" |
| size='mini' |
| > |
| <slot name="formItem" /> |
| <el-form-item |
| v-for="(item,index) in formConfig.formItemList" |
| :key="index" |
| :label="item.label" |
| :prop="item.prop" |
| > |
| <el-input |
| v-if="item.type=='input'" |
| v-model="value[item.prop]" |
| :disabled="item.disabled" |
| :clearable="true" |
| :placeholder="item.placeholder" |
| ></el-input> |
| <el-select |
| :clearable="true" |
| v-else-if="item.type=='select'" |
| v-model="value[item.prop]" |
| :disabled="item.disabled" |
| :placeholder="item.placeholder" |
| > |
| <el-option |
| v-for="(optItem,index) in item.optList" |
| :key="index" |
| :label="optItem.label" |
| :value="optItem.value" |
| ></el-option> |
| </el-select> |
| <el-date-picker |
| :value-format="item.dateFormate" |
| v-else |
| v-model="value[item.prop]" |
| :type="item.type" |
| :disabled="item.disabled" |
| :clearable="true" |
| :placeholder="item.label" |
| ></el-date-picker> |
| </el-form-item> |
| <div class="searchBtn"> |
| <el-button-group> |
| <el-button |
| v-for="(item, index) in formConfig.operate" |
| :key="index" |
| size="small" |
| :type="item.type" |
| :icon="item.icon" |
| @click="item.handleClick" |
| >{{item.name}} |
| </el-button> |
| </el-button-group> |
| <slot name="operate"></slot> |
| </div> |
| </el-form> |
| </template> |
| <script> |
| export default { |
| components: {}, |
| props: { |
| formConfig: { |
| type: Object, |
| required: true |
| }, |
| value: { |
| type: Object, |
| required: true |
| }, |
| rules: { |
| type: Object |
| } |
| }, |
| computed: {}, |
| methods: { |
| setDefaultValue() { |
| const formData = { ...this.value }; |
| |
| this.formConfig.formItemList.forEach(({ key, value }) => { |
| if (formData[key] === undefined || formData[key] === null) { |
| formData[key] = value; |
| } |
| }); |
| this.$emit("input", formData); |
| } |
| }, |
| mounted() { |
| this.setDefaultValue(); |
| } |
| }; |
| </script> |
复制
使用Vue的slot插槽来动态渲染各个表单项。通过传递不同的参数来确定表单项的类型、值和验证规则等。基本能够处理解决大多数的表单问题,并且与slot的完美组合,已经可以达到我们的需求要求。
这种方法的优点是灵活性较高,但需要手动编写大量模板代码,也容易出现一些兼容性问题。
2.实现表单动态渲染、可视化配置的方法,动态表单又可以分为两种方法:(注意:注意 v-model 的绑定问题, 组件内不能直接修改props 。)
- 首先,需要配置 el-form :
| <template> |
| <el-form |
| class="dynamic-form" |
| :inline="formConfig.inline" |
| :model="value" |
| :label-position="formConfig.labelPosition" |
| :label-width="formConfig.labelWidth" |
| :size='formConfig.size' |
| :status-icon="formConfig.statusIcon"> |
| <slot/> |
| </el-form> |
| </template> |
| <script> |
| export default { |
| props: { |
| formConfig: { |
| type: Object, |
| required: true |
| }, |
| value: { |
| type: Object, |
| required: true |
| } |
| }, |
| methods: { |
| setDefaultValue() { |
| const formData = { ...this.value }; |
| |
| this.formConfig.formItemList.forEach(({ key, value }) => { |
| if (formData[key] === undefined || formData[key] === null) { |
| formData[key] = value |
| } |
| }); |
| this.$emit('input', formData) |
| } |
| }, |
| mounted() { |
| this.setDefaultValue() |
| }, |
| } |
| </script> |
复制
- 开始渲染 form-item :
- 第一种,利用 vue 内置的 component 组件,写起来可能像这样:
| <el-form-item> |
| <component :is="`el-${item.type}`" /> |
| </el-form-item> |
复制
| <el-form-item> |
| <el-input v-if="item.type === 'input'" /> |
| <span v-else>未知控件类型</span> |
| </el-form-item> |
复制
简单介绍
| <template> |
| <el-form-item :label="label"> |
| <el-select v-model="currentValue" @input="onInputEvent" size="small"> |
| <el-option |
| v-for="item in options" |
| :key="item.value" |
| :label="item.label" |
| :value="item.value"> |
| </el-option> |
| </el-select> |
| </el-form-item> |
| </template> |
| |
| <script> |
| import formMixins from '~/components/Form/iForm/form-model' |
| export default { |
| name: "SelectList", |
| props: ['name', 'label', 'value', 'options'], |
| mixins: [formMixins], |
| data() { |
| return { |
| currentValue: this.value |
| } |
| } |
| } |
| </script> |
复制
由于每个表单组件都是监听父元素的value值变化,数据变化时都是触发onInputEvent并执行this.$emit(‘input’),所以我们可以把这部分内容抽取出来放在mixins里面。
| export default { |
| props: ['name', 'value'], |
| |
| data () { |
| return { |
| currentValue: this.value |
| }; |
| }, |
| methods: { |
| onInputEvent(value) { |
| this.$emit('input', this.name, value); |
| }, |
| reset() { |
| this.currentValue = ""; |
| } |
| }, |
| watch: { |
| value (val) { |
| this.currentValue = val; |
| } |
| } |
| }; |
复制
3. 动态生成表单
这里主要是根据配置的数据,循环生成表单组件。默认提供提交和重置按钮,如果不需要可以通过slot传递其他操作按钮。这里的要点主要有: 监听表单组件的数据变化: 每个表单组件都有一个name标识它的业务含义,绑定的数据也是formData[field.name],@input事件传递updateForm,在updateForm里面更新this.formData[name],保证了this.formData里面的数据是和表单组件选择/填写的内容一致。 重置时改变表单组件的数据: 因为组件内部会监听父元素的value,所以这里只要清空this.formData的值,组件内部的数据也会跟着清空。
| <template> |
| <div> |
| <el-form :inline="true" ref="form" :model="formData" class="demo-form-inline"> |
| <el-col :span="field.cols" v-for="(field, index) in config.fieldsConfig" v-bind:key="index"> |
| <component :key="index" |
| :is="field.fieldType" |
| :label="field.label" |
| :value="formData[field.name]" |
| :multiple="field.multiple" |
| @input="updateForm" |
| v-bind="field" |
| :options="field.options" |
| :ref="field.name" |
| > |
| </component> |
| </el-col> |
| <slot name="buttons"> |
| <el-button type="primary" @click="submit" size="small">{{onSubmitText}}</el-button> |
| <el-button type="default" @click="reset" size="small">{{onResetText}}</el-button> |
| </slot> |
| </el-form> |
| </div> |
| </template> |
| |
复制