vue封装动态表单组件,可外部配置表单项事件

动态配置的表单组件常见,但手动封装的动态表单组件如何实现表单项事件也可外部配置是一个常见难题,下面这个组件可以利用高阶函数实现表单项基本事件外部配置,也许可以给大家一点思路,如果大家喜欢或者感觉有帮助就给文章点个赞吧~

一、封装组件代码

<template>
  <div class="form" v-if="formConfig">
    <el-form
      ref="formDom"
      :model="formData"
      :rules="formRules"
      :inline="inline"
      :label-width="labelWidth"
      :label-position="labelPosition"
    >
      <el-form-item
        v-for="(item, key, index) in formConfig"
        :key="key"
        :label="item.label"
        :label-width="item.labelWidth || '100'"
        :prop="key"
        :style="item.style"
        v-if="!item.hide"
      >
        <!-- 只列出focus blur change事件举例,更多事件可以自行添加绑定 -->
         <el-input
          v-if="item.type === 'input'"
          v-model="formData[key]"
          :disabled="item.disabled"
          :type="item.inputType ? item.inputType : 'text'"
          :placeholder="item.placeholder || `请输入${item.label}`"
          clearable
          @focus="(e) => issueEvent(e, item.onFocus)"
          @blur="(e) => issueEvent(e, item.onBlur)"
          @change="(e) => issueEvent(e, item.onChange)"
        />

        <el-select
          v-if="item.type === 'select'"
          v-model="formData[key]"
          clearable
          :disabled="item.disabled"
          :placeholder="item.placeholder || `请选择${item.label}`"
          :multiple="item.multiple"
          :filterable="item.filterable"
          :max-tag-count="item.max_tag_count"
          style="width: 100%"
          @change="(e) => issueEvent(e, item.onChange)"
        >
          <el-option
            v-for="list in item.options"
            :key="list.value"
            :value="list.value"
            :label="list.label"
          >
          </el-option>
        </el-select>

        <slot name="item" />

        <el-button
          v-if="item.type === 'confirm'"
          type="primary"
          :loading="item.isSearching"
          @click="submit"
        >
          查询
        </el-button>

        <el-button v-if="item.type === 'reset'" type="primary" @click="reset">
          重置
        </el-button>

        <slot name="button" />
      </el-form-item>

      <slot name="form" />
    </el-form>
  </div>
</template>

<script>
export default {
  name: "customForm",
  props: {
    // 表单项是否行内显示
    inline: {
      type: Boolean,
      default: true,
    },
    // 表单项配置
    formConfig: {
      type: Object,
      default: () => {},
    },
    // 表单项数据
    formDataInit: {
      type: Object,
      default: () => {},
    },
    // 表单标签宽度
    labelWidth: {
      type: [Number, String],
      default: "100",
    },
    // 表单标签位置,默认左侧
    labelPosition: {
      type: String,
      default: "left",
    },
    // 表单校验规则
    formRules: {
      type: Object,
      default: () => {},
    },
  },
  data() {
    return {
      formData: this.formDataInit,
      selectKeys: [],
    };
  },
  methods: {
    //重点在issueEvent函数,可以给事件绑定一个空函数避免报错,如果有外部传入的自定义函数则返回这个函数
    /*组件内函数负责分发表单项事件 */
    issueEvent(value, mouseEvent) {
      if (mouseEvent) {
        return mouseEvent(value);
      }
    },
    submit() {
      this.$emit("submit");
    },
    reset() {
      this.$refs.formDom.resetFields();
    },
  },
};
</script>

<style lang="less" scoped>
</style>

二、引入并使用组件

<template>
  <div>
    这里是测试页 测试引入组件
    <customForm
      :formDataInit="formDataInit"
      :form-config="formConfig"
      :label-width="'70'"
      :form-rules="formRules"
      @submit="getList"
    />
  </div>
</template>

<script>
import customForm from "@/components/customForm";
export default {
  components: {
    customForm,
  },
  data() {
    return {
      isSearching: false, // // 是否查询中
      // 表单配置
      formConfig: {
        id: {
          label: "id",
          type: "input",
          // disabled: true,
          placeholder: "看看提示语",
          // style:'display:none;',
          // hide:false,//表单项是否隐藏
          onFocus: () => {//给表单项配置事件及具体操作
            console.log(23232, this);
          },
          //   onChange: () => {
          //     // console.log(1);
          //   },
          //   onBlur: () => {
          //     console.log(888);
          //   },
        },
        ids: {
          label: "项目id",
          type: "input",
          //   onFocus: () => {
          //     console.log(565656);
          //   },
          //   onChange: () => {
          //     console.log(1);
          //   },
          //   onBlur: () => {
          //     // console.log(1);
          //   },
        },
        status: {
          label: "状态",
          type: "select",
          //   multiple: true, // 是否支持多选
          max_tag_count: 1, // 多选时最多显示多少个 tag
          options: [
            {
              label: "数据一",
              value: "0",
            },
            {
              label: "数据二",
              value: "1",
            },
          ], // select选择项列表
          onChange: (value, label, arr) => {
            console.log(value, label, arr);
            if (value == "0") {
              this.formConfig["id"].disabled = false;
            } else {
              this.formConfig["id"].disabled = true;
            }
            console.log("this.formDataInit", this.formDataInit);
          },
        },
        time: {
          label: "开始时间",
          type: "daterange",
        },
        confirm: {
          text: "查询", // 按钮文案
          type: "confirm",
          label: "",
          labelWidth: 0,
          isSearching: this.isSearching,
        },
      },
      // 表单数据
      formDataInit: {
        id: "",
        page_number: 1,
        page_size: 10,
        time: [],
      },
      // 表单校验规则
      formRules: {
        id: [
          { required: true, message: "请输入id", trigger: "blur" },
          { min: 3, max: 5, message: "长度在 3 到 5 个字符", trigger: "blur" },
        ],
        status: [{ required: true, message: "请选择", trigger: "change" }],
      },
    };
  },
  methods: {
    getList() {
      console.log("提交了", this.formDataInit);
    },
  },
};
</script>

<style lang="less" scoped></style>

猜你喜欢

转载自blog.csdn.net/Sylvasylva/article/details/129178148