基于element-ui实现的vue版的动态表单

日常开发中 有大量的表单需要填写 涉及到表单 就会有 对于表单的验证 还有就是表单中的顺序 比如 一开始需求是 实现一个表单


饿了么的代码

<el-form ref="form" :model="form" label-width="80px">
  <el-form-item label="姓名">
    <el-input v-model="form.name"></el-input>
  </el-form-item>
  <el-form-item label="学历">
    <el-select v-model="form.edu" >
      <el-option label="本科" value="1"></el-option>
      <el-option label="硕士" value="2"></el-option>
      <el-option label="博士" value="3"></el-option>
    </el-select>
  </el-form-item>
  <el-form-item label="年龄">
    <el-input v-model="form.age"></el-input>
  </el-form-item>
</el-form>
export default {
  data () {
    return {
      form: {
        name: '',
        edu: '',
        age: ''
      }
    }
  }
}复制代码

功能确实实现了,但我认为不够灵活 不能配置

我的动态组件的代码

<ccms-form :form-list="formList"></ccms-form>复制代码
<script>
  import * as Util from './util'
  export default {
    data () {
      return {
        formList: [  {
    label: '姓名',
    prop: 'name',
    itemType: 'input',
    model: '',
    rules: [],
    focus: function () {}
  },
  {
    label: '学历',
    prop: 'edu',
    itemType: 'select',
    options: [{label: '本科', value: '1'}, {label: '硕士', value: '2'}, {label: '硕士', value: '3'}],
    model: ''
  },
  {
    label: '年龄',
    prop: 'age',
    itemType: 'input',
    model: ''
  }
]
      }
    }
  }
</script>复制代码

这个就像当于把表单作为了一个配置文件 这里可以所有的配置规则 详细的可以去看下我的demo 

表单组件的部分源码 就是内部要尽可能的写出这个表单项的所有事件及属性 而且表单项现在在考虑动态加载 一个表单可能不止有input select radiobox checkBox等等 种类扩展以后就可以实现基于后台的自动化配置 

/**
 * Created by sch on 2017/11/14.
 */
<template>
  <div class="ccms-form">
  <el-form ref="form" :model="formModel" label-width="150px">
  <div class="row-item" v-for="(formItem, index) in formModel.formList" :key="index" v-show="formItem.show">
    <el-form-item :show-message="!formItem.hiddenMsg" :rules= "formItem.disabled?[]:formItem.rules" :label="formItem.label" :prop="'formList.' + index + '.model'" >
      <cc-input
        v-if="formItem.itemType === 'input'"
        :type="formItem.type"
        :maxlength="formItem.maxlength"
        :minlength="formItem.minlength"
        v-model.trim="formItem.model"
        :placeholader="formItem.placeholder"
        :disabled="formItem.disabled"
        :auto-complete="formItem.autoComplete"
        :max="formItem.max"
        :min="formItem.min"
        :step="formItem.step"
        :name="formItem.name"
        :resize="formItem.resize"
        :autofocus="formItem.autofocus"
        :form="formItem.form"
        :icon="formItem.icon"
        :rows="formItem.rows"
        :autosize="formItem.autosize"
        :size="formItem.size"
        :readonly="formItem.readonly"
        :on-icon-click="formItem.handleIconClick"
        @click="typeof formItem.click === 'function'?formItem.click($event):function() {}"
        @blur="typeof formItem.blur === 'function'?formItem.blur($event): function(){}"
        @focus="typeof formItem.focus === 'function'?formItem.focus($event): function(){}"
        @change="typeof formItem.change === 'function'?formItem.change($event): function(){}"></cc-input>
      <el-autocomplete
        v-if="formItem.itemType === 'autocomplete'"
        :placeholader="formItem.placeholder"
        :disabled="formItem.disabled"
        v-model.trim="formItem.model"
        :custom-item="formItem.customItem"
        :fetch-suggestions="formItem.fetchSuggestions"
        :popper-class="formItem.popperClass"
        :trigger-on-focus="formItem.triggerOnFocus"
        :on-icon-click="formItem.onIconClick"
        :icon="formItem.icon"
        @select="typeof formItem.select === 'function'?formItem.select($event): function(){}"
      ></el-autocomplete>
      <el-select
        :multiple ="formItem.multiple"
        :clearable= "formItem.clearable"
        :size="formItem.size"
        :multiple-limit="formItem.multipleLimit"
        :name="formItem.name"
        :placeholder="formItem.placeholder"
        :allow-create="formItem.allowCreate"
        :disabled="formItem.disabled"
        :filter-method="formItem.filterMethod"
        :filterable="formItem.filterable"
        :loading-text="formItem.loadingText"
        :no-data-text="formItem.noDataText"
        :popper-class="formItem.popperClass"
        :no-match-text="formItem.noMatchText"
        :loading="formItem.loading"
        :remote="formItem.remote"
        :remote-method="formItem.remoteMethod"
        v-model="formItem.model"
        v-if="formItem.itemType === 'select'"
        @change="selectChange.call(null,formItem.change,$event)"
        @visible-change="typeof formItem.visibleChange === 'function'?formItem.visibleChange($event): function(){}"
        @remove-tag="typeof formItem.removeTag === 'function'?formItem.removeTag($event): function(){}">
        <el-option
          v-for="item in formItem.options"
          :key="item.value"
          :label="item.label"
          :value="item.value"
          :disabled="item.disabled"
        ></el-option>
      </el-select>
    </el-form-item>
  </div>
    <el-row class="btn-group" v-if="needBtn">
      <!--<el-button @click="clickCancel">重置</el-button>-->
      <el-button type="primary" @click="clickSubmit">保存</el-button>
    </el-row>
    <el-row class="btn-group">
      <slot  name="btn-group"></slot>
    </el-row>
  </el-form>
  </div>
</template>
<script>
  let vm = {}
//  import * as Model from './model'
  export default{
    name: 'CcmsForm',
    data () {
      this.turnData(this.formList)
      return {
        vm: vm,
        refForm: {},
        formModel: {
          formList: this.formList
        }
      }
    },
    props: {
      formList: Array,
      needBtn: {
        type: Boolean,
        default: true
      }
    },
    watch: {
      formList (val) {
        this.formModel.formList = val
        this.turnData(this.formModel.formList)
      }
    },
    mounted () {
      this.setAuth()
      this.refForm = this.$refs['form']
    },
    methods: {
//    通过一个prop字段设置另一个属性 prop tarPro要设置的目标属性值
      setProperByPro (prop, tarPro) {
        if (typeof tarPro !== 'object') {
          return
        }
        for (let i = 0; i < this.formList.length; i++) {
          if (this.formList[i].prop === prop) {
            for (let key in tarPro) {
              this.formList[i][key] = tarPro[key]
            }
          }
        }
      },
      // 通过prop 获取表单字段对象
      getPropObjByPro (prop) {
        for (let i = 0; i < this.formList.length; i++) {
          if (this.formList[i].prop === prop) {
            return this.formList[i]
          }
        }
      },
      // 设置权限控制
      setAuth () {
        this.formList.map(item => {
          if (typeof item.dataAuth === 'function') {
            item.dataAuth()
          }
        })
      },
      // 点击确认按钮
      clickSubmit () {
        this.$refs['form'].validate(val => {
          if (val) {
            this.$emit('clickSubmit', this.getFormModel())
          }
        })
      },
      // 获取form model
      getFormModel () {
        let workObj = {}
        for (let i = 0; i < this.$refs['form'].model.formList.length; i++) {
          let obj = this.$refs['form'].model.formList[i]
          workObj[obj.prop] = obj.model
        }
        return workObj
      },
      // 重置表单
      reset () {
        this.$refs.form.resetFields()
      },
      // 点击取消按钮
      clickCancel () {
        this.$emit('clickCancel', this.$refs['form'])
      },
      // 当一个表单域从enable 变为disabled时 enabled错误信息不显示
      hiddenMsg () {
        for (let i = 0; i < this.formList.length; i++) {
          if (this.formList[i].disabled) {
            this.formList[i].hiddenMsg = true
          } else {
            this.formList[i].hiddenMsg = false
          }
        }
      },
      selectChange (fun, val) {
        if (typeof fun === 'function') {
          fun(val)
        }
        this.setAuth()
        this.hiddenMsg()
      },
      turnData (formList) {
        for (let i = 0; i < formList.length; i++) {
          let item = formList[i]
          if (item.show === undefined) {
            item.show = true
          }
          if (item.disabled === undefined) {
            item.disabled = false
          }
        }
      }
    }
  }
</script>

复制代码
这是github地址 https://github.com/teenth/ccmsui复制代码

欢迎指正


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值