前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >总结form表单的三种封装方法(Vue+ElementUI)

总结form表单的三种封装方法(Vue+ElementUI)

作者头像
用户2323866
修改2021-06-25 10:13:19
6.8K0
修改2021-06-25 10:13:19
举报
文章被收录于专栏:技术派

1.首先是最普通,也是大家最先想到的方法,直接封装:

代码语言:javascript
复制
<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>

第一种方法简单明了,基本能够处理解决大多数的表单问题,并且与slot的完美组合,已经可以达到我们的需求要求。

2.实现表单动态渲染、可视化配置的方法,动态表单又可以分为两种方法:

首先,需要配置 el-form :

代码语言:javascript
复制
<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 组件,写起来可能像这样:
代码语言:javascript
复制
<el-form-item>
 <component :is="`el-${item.type}`" />
</el-form-item>
  • 第二种,使用 v-if 逐个判断:
代码语言:javascript
复制
<el-form-item>
 <el-input v-if="item.type === 'input'" />
 <span v-else>未知控件类型</span>
</el-form-item>

考虑到每种表单控件的处理逻辑千差万别,这里本博主先介绍第一种(为了防止有人照搬,这里本博主只做简单介绍,不懂得私信):

代码语言:javascript
复制
<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里面。

代码语言:javascript
复制
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;
        }
    }
};

动态生成表单

这里主要是根据配置的数据,循环生成表单组件。默认提供提交和重置按钮,如果不需要可以通过slot传递其他操作按钮。这里的要点主要有: 监听表单组件的数据变化: 每个表单组件都有一个name标识它的业务含义,绑定的数据也是formData[field.name],@input事件传递updateForm,在updateForm里面更新this.formData[name],保证了this.formData里面的数据是和表单组件选择/填写的内容一致。 重置时改变表单组件的数据: 因为组件内部会监听父元素的value,所以这里只要清空this.formData的值,组件内部的数据也会跟着清空。

代码语言:javascript
复制
<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>

动态加载的第二种方法不多介绍,只提醒一句,注意 v-model 的绑定问题, 组件内不能直接修改props 。

温馨提示:

你需要知道 v-model 的工作原理 :

代码语言:javascript
复制
<input v-model="something">

这不过是以下示例的语法糖:

代码语言:html
复制
<input
 :value="something"
 @input="something = $event.target.value">

本文系转载,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文系转载前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1.首先是最普通,也是大家最先想到的方法,直接封装:
  • 2.实现表单动态渲染、可视化配置的方法,动态表单又可以分为两种方法:
    • 动态生成表单
      • 温馨提示:
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档