Vue实现动态表单

280 阅读1分钟

封装两个简单的表单组件

通过value change 实现v-model双向绑定

<template>
  <div v-if="item">
    <a-form-model-item
      :label="item.title"
      :prop="item.name"
      :rules="item.rules"
    >
      <a-input style="width: 120px" :value="value" @input="handleChange">
      </a-input>
    </a-form-model-item>
  </div>
</template>

<script>
export default {
  props: {
    item: {
      type: Object,
      default: () => {},
    },
    defaultKey: {
      type: String,
      default: "",
    },
  },
  data() {
    return {
      value: this.item.val,
    };
  },
  methods: {
    handleChange({target:{value}}) {
        console.log(value)
      this.value = value;
      this.$emit("changeComponent", { key: this.defaultKey, value: value });
    },
  },
};
</script>

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

<template>
  <div v-if="item">
    <a-form-model-item
      :label="item.title"
      :prop="item.name"
      :rules="item.rules"
    >
      <a-select
        style="width: 120px"
        :options="item.selectObj"
        :value="value"
        @change="handleChange"
      >
      </a-select>
    </a-form-model-item>
  </div>
</template>

<script>
export default {
  props: {
    item: {
      type: Object,
      default: () => {},
    },
    defaultKey: {
      type: String,
      default: "",
    },
  },
  data() {
    return {
      value: this.item.val,
    };
  },
  methods: {
    handleChange(val) {
      this.value = val;
      this.$emit("changeComponent", { key: this.defaultKey, value: val });
    },
  },
};
</script>

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

使用Vue动态组件的形式进行渲染动态表单

也可以传入数组下标,这个参数用来标识当前组件位于动态表单的第几个,方便后期对数据的操作。

<template>
  <div class="home">
    <a-form-model ref="ruleForm" :model="form">
      <component
        v-for="item in formList"
        :key="item.name"
        :item="item"
        :is="item.type"
        :defaultKey="item.name"
        @changeComponent="changeComponentHandler"
      ></component>
      <a-button type="primary" @click="onSubmit"> Create </a-button>
    </a-form-model>
  </div>
</template>

<script>
import Select from "@/components/select";
import Input from "@/components/input";
export default {
  name: "Happyb",
  components: {
    Select,
    Input,
  },
  data() {
    return {
      formList: [
        {
          name: "name",
          type: "Select",
          title: "选择",
          val: null,
          rules: {
            required: true,
            message: "Please input Activity name",
            trigger: "blur",
          },
          selectObj: [
            { value: "1", label: "测试" },
            { value: "2", label: "开发" },
          ],
        },
        {
          name: "age",
          type: "Input",
          title: "输入",
          rules: {
            required: true,
            message: "Please input Activity age",
            trigger: "blur",
          },
          val: null,
        },
      ],
      form: {},
    };
  },
  mounted() {
    this.form = this.formList.reduce((pre, cur) => {
      pre[cur["name"]] = cur["val"];
      return pre;
    }, {});
    console.log(this.form);
  },
  methods: {
    changeComponentHandler({ key, value }) {
      this.form[key] = value;
      console.log(this.form);
    },
    onSubmit() {
      this.$refs.ruleForm.validate((valid) => {
        if (valid) {
          alert("submit!");
        } else {
          console.log("error submit!!");
          return false;
        }
      });
    },
  },
};
</script>