老默 ,我想搞form表单了 , 去给我封装一个动态表单

        前言:之前碰到一个需求,一个页面,有16个表单,根据下拉框的值去切换表单,如果页面里一个一个的写,页面太冗长了!秉承一个页面不超过500行的代码风格,我把表单根据element-ui进行了二次封装。

所有的内容都写在了代码中,不懂得地方查看注释🐶🐶

父组件引用:

html部分

<template>
  <div class="container">
    <h3>form表单封装案例</h3>
    <div style="margin: 10px">
      根据下拉框的值改变form表单:
      <el-select v-model="value" placeHolder="请选择" @change="handleChange">
        <el-option
          v-for="item in options"
          :key="item.value"
          :value="item.value"
          :label="item.label"
        >
        </el-option>
      </el-select>
    </div>
// 仅关注这里即可,上面是表单切换触发的条件
    <PublicForm
      ref="PublicForm"
      :formModel="formObj"
      :formItemList="formItemList"
    ></PublicForm>
  </div>
</template>

JS部分

<script>
import PublicForm from './PublicForm';
// ⚠️⚠️⚠️ 注意这里引入了一个js文件,是form表单的配置
import { form1, formList1, form2, formList2 } from './formConfig.js';
export default {
  name: 'myForm',
  components: { PublicForm },
  data() {
    return {
      value: '1',
      options: [
        { value: '1', label: 'Form1表单' },
        { value: '2', label: 'Form2表单' },
      ],
// ⚠️⚠️⚠️⚠️⚠️⚠️⚠️,注意这里,是父组件传的参数
      formObj: form1,
      formItemList: formList1,
    };
  },
  methods: {
// 这里是下拉框选择事件,可忽略
    handleChange(val) {
      // 下拉框的值变化,form表单的内容也变化
      switch (val) {
        case '1':
          // 切换下拉框的选项,form表单的配置随之改变
          this.formObj = form1;
          this.formItemList = formList1;
          break;
        case '2':
          this.formObj = form2;
          this.formItemList = formList2;
          break;
        default:
          break;
      }
    },
  }
};
</script>

❕❕❕form表单配置的js文件,这里注意看

formConfig.js文件

// form表单的所有字段
export const form1 = {
  name: '', // 姓名
  gender: '1', // 性别 可以配置表单默认值
  height: '' // 身高
}
// form表单每个字段对应的配置信息,你是下拉框还是输入框还是单选按钮?在这里配置
export const formList1 = [
  {
    type: 'input',
    label: '姓名',
    key: 'name', // 跟上面的姓名字段对应
    rules: [{ required: true, message: '请输入姓名', trigger: ['blur', 'change'] }]
  },
  {
    type: 'select',
    label: '性别',
    key: 'gender',
    options: [
      { value: '1', label: '男' },
      { value: '0', label: '女' },
    ],
  },
  {
    type: 'input',
    label: '身高',
    key: 'height', // 跟上面的姓名字段对应
    rules: [{ required: true, message: '请输入身高', trigger: ['blur', 'change'] }]
  },
]


export const form2 = {
  targetName: '', // 指标名称
  isImportant: '1', // 是否重要 也可以设置默认值
  targetDate: '2023-01-01' // 指标日期 也可以设置默认值
}
export const formList2 = [
  {
    type: 'input',
    label: '指标名称',
    key: 'targetName',
  },
  {
    type: 'radio',
    label: '是否重要',
    key: 'isImportant',
    options: [
      { value: '1', label: '重要' },
      { value: '0', label: '不重要' },
    ],
  },
  {
    type: 'time', // 日期组件的话还需要设定timeType ,比如时间范围 daterange
    timeType: 'date',
    label: '指标日期',
    key: 'targetDate',
  },
]

子组件:

html部分

<template>
  <div>
    <el-form
      ref="publicFormRef"
      :model="formModel"
      v-bind="$attrs"
      :label-width="formConfig.labelWidth"
    >
      <el-row>
        <el-col :span="item.span || 10" v-for="item in formItemList" :key="item.key">
          <template>
            <el-form-item
              class="list-item-class"
              :key="item.key"
              :rules="item.rules"
              :label="item.label ? item.label + ':' : ''"
              :prop="item.key"
            >
              <!-- 输入框 -->
              <el-input
                v-if="item.type == 'input'"
                :placeholder="item.placeholder || '请输入' + item.label"
                v-model="formModel[item.key]"
                :type="item.inputType || 'text'"
                :maxlength="item.maxlength || 100000"
                :minlength="item.minlength || 0"
                @input="item.inputEvent && item.inputEvent($event, item.key)"
                :show-word-limit="item.limit"
                :disabled="item.disabled"
                clearable
              ></el-input>
              <!-- 下拉框 -->
              <el-select
                v-else-if="item.type == 'select'"
                v-model="formModel[item.key]"
                :placeholder="item.placeholder || '请选择' + item.label"
                :disabled="item.disabled"
              >
                <!-- 这里注意,options的内容需是value和label,如果不是,需要在父组件map处理一下再传,方法如下 -->
                <!-- handleOption(options) {
              // 假如你的是 id 和 text [{id:1,text:'aa'},{id:2,text:'bb'}] => [{value:1,label:'aa'},{value:2,label:'bb'}]
              options.map(obj => {
                return { value: obj.id, label: obj.text };
              });
            }, -->
                <el-option
                  v-for="opt in item.options"
                  :label="opt.label"
                  :value="opt.value"
                  :key="opt.value"
                >
                </el-option>
              </el-select>
              <!-- 这里默认的日期格式看自己的项目需求,目前默认 yyyy-MM-dd -->
              <!-- 如需添加新功能(例如日期图标 ),请自行设置-->
              <el-date-picker
                v-else-if="item.type == 'time'"
                v-model="formModel[item.key]"
                :type="item.timeType"
                :unlink-panels="item.unlinkPanels"
                :start-placeholder="item.timeType === 'daterange' ? '开始日期' : ''"
                :end-placeholder="item.timeType === 'daterange' ? '结束日期' : ''"
                :value-format="item.valueFormat || 'yyyy-MM-dd'"
                :placeholder="
                  item.timeType === 'date' ? item.placeholder || '请选择日期' : ''
                "
                :picker-options="item.pickerOptions || pickerOptions"
              >
              </el-date-picker>
              <!-- 单选按钮 -->
              <el-radio-group
                v-else-if="item.type == 'radio'"
                :disabled="item.disabled"
                v-model="formModel[item.key]"
                @change="item.changeEvent && item.changeEvent($event, item.key)"
              >
                <el-radio v-for="opt in item.options" :key="opt.value" :label="opt.value"
                  >{{ opt.label }}
                </el-radio>
              </el-radio-group>

              <!-- 自定义项 -->
              <template v-else-if="custom">
                <slot name="item.customName"></slot>
              </template>
            </el-form-item>
          </template>
        </el-col>
      </el-row>
    </el-form>
  </div>
</template>

JS部分

⚠️⚠️⚠️:这里主要接受一个下拉框数据,要求的是value和label,当后端返回的下拉数据不符合要求时,可以自己做一个map循环,处理一下数据。可以参考html部分中的下拉框部分的注视,有写明。

<script>
export default {
  name: 'PublicForm',
  props: {
    // 表单的额外配置
    formConfig: {
      type: Object,
      default: () => {
        return {
          labelWidth: '150px',
        };
      },
    },
    // form表单的所有字段
    formModel: {
      type: Object,
      required: true,
    },
    // form表单中每个formItem的配置
    formItemList: {
      type: Array,
      default: () => [],
    },
  },
  computed: {},
  watch: {
    formItemList: {
      handler(e) {
        this.formItemList = e;
      },
    },
  },
  data() {
    return {
      // 默认不能选择今天之后的时间
      pickerOptions: {
        disabledDate(time) {
          return time.getTime() > Date.now();
        },
      },
    };
  },
  methods: {
// 需要提交和重置功能可以通过ref调用如下方法,或自行修改
    submitForm() {
      this.$refs['publicFormRef'].validate(valid => {
        this.$emit('onSubmit', valid);
      });
    },
    resetForm() {
      this.$refs['publicFormRef'].resetFields();
      this.$emit('onReset');
    },
  },
};
</script>

       

        封装大部分是根据自己的需求来封装的,如果是基本的form表单,没有特别复杂的逻辑交互,完全可以C/V拿来用。

        转载请标明出处,谢谢!

        有很多不到位的地方,也有一些没表达清楚的部分,欢迎批评指正

  • 4
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值