基於element-ui實現的vue版的動態表單

teenth發表於2018-07-23

日常開發中 有大量的表單需要填寫 涉及到表單 就會有 對於表單的驗證 還有就是表單中的順序 比如 一開始需求是 實現一個表單

基於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複製程式碼

歡迎指正


相關文章