封装一个elementui的form组件

子组件

<template>
  <div class="formDiv">
    <el-form
      ref="form"
      :model="form"
      :inline="inline"
      :rules="rules"
      :label-width="labelWidth"
      :class="{ flexForm: flex }"
    >
      <el-form-item
        :label="item.title"
        :prop="item.key"
        v-for="item in options"
        :key="item.key"
      >
        <div v-if="$slots[item.key]">
          <slot :name="item.key"></slot>
        </div>
        <div v-else>
          <el-input
            :size="size"
            v-model="form[item.key]"
            v-if="item.type === 'text'"
            :placeholder="
              item.placeholder ? item.placeholder : '请输入' + item.title
            "
            :disabled="item.disabled"
            clearable
          ></el-input>
          <el-input
            :size="size"
            type="textarea"
            :autosize="{ minRows: 3, maxRows: 6 }"
            :placeholder="
              item.placeholder ? item.placeholder : '请输入' + item.title
            "
            v-model="form[item.key]"
            v-if="item.type === 'textarea'"
            :disabled="item.disabled"
          >
          </el-input>
          <el-input
            v-if="item.type === 'password'"
            type="password"
            placeholder="请输入密码"
            v-model="form[item.key]"
          ></el-input>
          <el-switch
            :size="size"
            v-model="form[item.key]"
            v-if="item.type === 'switch'"
            active-color="#13ce66"
            inactive-color="#ff4949"
            :disabled="item.disabled"
          >
          </el-switch>
          <el-time-picker
            :size="size"
            :placeholder="
              item.placeholder ? item.placeholder : '请选择' + item.title
            "
            v-model="form[item.key]"
            value-format="HH:mm:ss"
            v-if="item.type === 'time'"
            :disabled="item.disabled"
          >
          </el-time-picker>
          <el-date-picker
            type="date"
            :placeholder="
              item.placeholder ? item.placeholder : '请选择' + item.title
            "
            value-format="yyyy-MM-dd"
            :size="size"
            v-model="form[item.key]"
            v-if="item.type === 'date'"
            :disabled="item.disabled"
          ></el-date-picker>
          <el-date-picker
            type="datetime"
            :placeholder="
              item.placeholder ? item.placeholder : '请选择' + item.title
            "
            value-format="yyyy-MM-dd HH:mm:ss"
            :size="size"
            v-model="form[item.key]"
            v-if="item.type === 'datetime'"
            :disabled="item.disabled"
          ></el-date-picker>
          <el-date-picker
            type="daterange"
            range-separator="至"
            start-placeholder="开始日期"
            end-placeholder="结束日期"
            value-format="yyyy-MM-dd HH:mm:ss"
            :size="size"
            v-model="form[item.key]"
            v-if="item.type === 'date-to-date'"
            :disabled="item.disabled"
          ></el-date-picker>
          <el-date-picker
            type="datetimerange"
            range-separator="至"
            start-placeholder="开始日期"
            end-placeholder="结束日期"
            value-format="yyyy-MM-dd HH:mm:ss"
            :size="size"
            v-model="form[item.key]"
            v-if="item.type === 'datetime-to-datetime'"
            :disabled="item.disabled"
          ></el-date-picker>
          <el-input-number
            :size="size"
            v-model="form[item.key]"
            v-if="item.type === 'number'"
            :disabled="item.disabled"
          ></el-input-number>
          <el-select
            :size="size"
            v-model="form[item.key]"
            v-if="item.type === 'select'"
            clearable
            :placeholder="
              item.placeholder ? item.placeholder : '请选择' + item.title
            "
            :disabled="item.disabled"
          >
            <el-option
              v-for="data in item.option.data"
              :key="data[item.option.props.key]"
              :label="data[item.option.props.label]"
              :value="data[item.option.props.value]"
            >
            </el-option>
          </el-select>
          <el-cascader
            :size="size"
            v-model="form[item.key]"
            v-if="item.type === 'cascader'"
            :disabled="item.disabled"
            :options="item.option.data"
            @change="cascaderChange"
            :props="item.option.props"
            filterable
          ></el-cascader>
          <el-radio-group
            :size="size"
            v-model="form[item.key]"
            v-if="item.type === 'radio'"
            :disabled="item.disabled"
          >
            <el-radio
              v-for="data in item.option.data"
              :key="data[item.option.props.key]"
              :label="data[item.option.props.value]"
              >{{ data[item.option.props.label] }}</el-radio
            >
          </el-radio-group>
          <el-checkbox-group
            :size="size"
            v-model="form[item.key]"
            v-if="item.type === 'checkbox'"
            :disabled="item.disabled"
          >
            <el-checkbox
              v-for="data in item.option.data"
              :key="data[item.option.props.key]"
              :label="data[item.option.props.label]"
              >{{ data[item.option.props.label] }}</el-checkbox
            >
          </el-checkbox-group>
          <el-upload
            v-if="item.type === 'file'"
            action="/api/upload_ajax"
            :show-file-list="false"
            :on-success="handleAvatarSuccess"
            :disabled="item.disabled"
          >
            <img
              v-if="form[item.key]"
              :src="form[item.key]"
              alt=""
              style="width: 178px; height: 178px; border-radius: 6px"
              @click="setFileKey(item.key)"
            />
            <i
              v-else
              class="el-icon-plus avatar-uploader-icon"
              @click="setFileKey(item.key)"
            ></i>
          </el-upload>
        </div>
      </el-form-item>
      <slot name="options"></slot>
    </el-form>
  </div>
</template>

<script>
export default {
  name: "index",
  props: {
    // flex布局
    flex: {
      type: Boolean,
      default: false,
    },
    // 表单
    form: {
      type: Object,
      default: function () {
        return {};
      },
    },
    // 表单配置
    options: {
      type: Array,
      default: function () {
        return [];
      },
    },
    // 表单验证规则
    rules: {
      type: Object,
      default: function () {
        return {};
      },
    },
    // 是否行内表单
    inline: {
      type: Boolean,
      default: function () {
        return false;
      },
    },
    // 表单表头宽度
    labelWidth: {
      type: String,
      default: function () {
        return "80px";
      },
    },
    // 控件大小
    size: {
      type: String,
      default: function () {
        return "medium";
      },
    },
  },
  data() {
    return {
      fileKey: "",
    };
  },
  mounted() {
    // 动态添加验证
    this.addRules(this.options);
    // 初始化完成清除一下表单验证规则
    this.$nextTick(function () {
      this.clearValidate();
    });
  },
  methods: {
    cascaderChange(value) {
      this.$emit("chooseGC", value);
    },
    /**
     * @description: 动态添加表单验证
     * @author: chenbz
     * @date: 2021/4/27
     */
    addRules(options) {
      for (let i = 0; i < options.length; i++) {
        // 判断是否需要添加验证
        if (options[i].rules) {
          // 判断用户是否已经自定义验证了
          if (!this.rules[options[i].key]) {
            // 动态生成验证方法
            let data = [
              {
                required: true,
                message: "",
                trigger: "",
              },
            ];
            // 动态添加验证方式:失去焦点触发/确认时触发
            if (options[i].type === ("input" || "text")) {
              data[0].message = "请输入" + options[i].title;
              data[0].trigger = "blur";
            } else {
              data[0].message = "请选择" + options[i].title;
              data[0].trigger = "change";
            }
            // 触发vue更新
            this.$set(this.rules, options[i].key, data);
          }
        }
      }
    },
    /**
     * @description: 表单验证
     * @author: chenbz
     * @date: 2021/5/10
     */
    validate() {
      let isValidate = false;
      this.$refs.form.validate((valid) => {
        if (valid) {
          isValidate = true;
          console.log("表单提交", this.form);
        }
      });
      return isValidate;
    },
    /**
     * @description: 清除表单验证
     * @author: chenbz
     * @date: 2021/5/18
     */
    clearValidate() {
      this.$refs.form.clearValidate();
    },
    setFileKey(key) {
      // console.log(key);
      this.fileKey = key;
    },
    handleAvatarSuccess(res, file) {
      // console.log(res);
      // console.log(file);
      file;
      this.form[this.fileKey] = res.data;
    },
  },
};
</script>

<style lang="less">
.formDiv {
  .flexForm {
    width: 100%;
    display: flex;
    justify-content: space-between;
    flex-wrap: wrap;
    .el-form-item {
      flex: 0 0 45% !important;
    }
  }
}
</style>

父组件

直接在父组件中如今并传入对应的数据就好,例如

formData: {
        flex: false, //开启flex布局
        form: {
          sex: "",
          name: "",
          account: "", //账号
          password: "", //密码
          gradeClass: "",
        },
        options: [
          {
            title: "名字",
            key: "name",
            type: "text",
            // rules: true,
          },
          {
            title: "账号",
            key: "account",
            type: "text",
            // rules: true,
          },
          {
            title: "密码",
            key: "password",
            type: "password",
            // rules: true,
          },

          {
            title: "年级/班级",
            key: "gradeClass",
            type: "cascader",
            option: {
              data: [],
              props: {
                value: "id", // 指定value对应data的字段
              },
            },
            // rules: true,
          },
        ],
        rules: {},
      },
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
的所有字段,如何获取表单数据并提交到后台? 对于封装elementui form的所有字段,可以在组件中分别定义各个字段属性,例如 v-model、placeholder、readonly等等。同时,需要在form表单中引入组件,并通过ref获取表单实例,再通过form实例上的submit方法提交数据到后台。具体实现过程可以参考以下代码示例: <template> <el-form ref="form" :model="formData" label-width="120px"> <el-form-item label="姓" prop="name"> <el-input v-model="formData.name" placeholder="请输入姓"></el-input> </el-form-item> <el-form-item label="年龄" prop="age"> <el-input v-model="formData.age" placeholder="请输入年龄"></el-input> </el-form-item> <el-form-item> <el-button type="primary" @click="handleSubmit">提交</el-button> </el-form-item> </el-form> </template> <script> export default { data() { return { formData: { name: '', age: '' } } }, methods: { handleSubmit() { this.$refs.form.validate(valid => { if (valid) { // 提交到后台的逻辑 console.log(this.formData) } else { return false } }) } } } </script> 在上述代码中,我们在组件中定义了两个字段属性name和age,并通过v-model绑定到formData对象上。然后在按钮点击事件中,通过this.$refs.form.validate方法来校验表单是否合法,如果合法则输出表单数据并提交到后台。注意,以上代码示例中只展示了如何获取表单数据并提交到后台,如果还需要对表单数据进行处理或者展示错误信息等逻辑,需要根据项目实际需要进行扩展。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值