欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

封装element-ui的table和form组件

程序员文章站 2022-05-30 20:33:59
...

element-ui的复杂

表格展示和修改数据是常见的业务需求,在element-ui中需要table和form组合使用,但是每次都需要一大堆代码,非常繁琐,我就尝试将两个组件结合,拥有功能为:能够修改表格中数据,数据校验,增加删除保存表格等功能。

第一个版本:主要由js

实现展示效果:类似于下图,可以直接通过
封装element-ui的table和form组件

<template>
  <div class="app-container">
    <el-container>

      <el-header>
        <span>配置</span>

      </el-header>

      <el-main>
        <my-table-page :table-head-datas="tableHeadDatas" :table-data-request="tableDataRequest"
                       :no-show-bottons="noShowBottons"
                       :table-data-request-params="tableDataRequestParams" child-component-path="configure/ScenarioDealQuotaDetail" add-component-path="configure/ScenarioDealQuotaDetail"
                       :insert-request="insertRequest" :is-pagination="true"  ></my-table-page>

      </el-main>


    </el-container>
  </div>
</template>

<script>
  //组件
  import MyTablePage from '@/components/commonComponents/MyTablePage'
  //组件  表头对象
  import {Rule, TableHeadData} from '@/components/commonComponents/TableObject'

  //请求  将axois请求封装成函数对象,进行调用
  import {getConfig,getType} from '@/api/configure'
  import {_req} from '@/utils/_req'

  //工具函数
  import {dateTimeFormate} from '@/utils/dateUtils'

  export default {
    name: "Config",
    /* 可用组件 */
    components: {MyTablePage},
    /* 数据 */
    data() {
      return {
        id: 0,
        tableHeadDatas: [],
        tableDataRequest: getMainConfigs,//function
        tableDataRequestParams: {},//object
        insertRequest: saveMainConfigs,
        noShowBottons: ["delete","refresh","save","add"]
      }
    },
    /* 计算方法 */
    computed: {},
    created() {
      let _self = this
      _self.versionId = _self.$route.query.versionId
      // console.log("dealQuota created")
      _self.tableDataRequestParams = {}
      _req.getOptions(getType,null,_self.tableHeadDatas,"dealQuotaCode")

      _self.tableHeadDatas.push(TableHeadData.createDefaultNoShow({id:id}))
      _self.tableHeadDatas.push(TableHeadData.createTableHeadData("dealQuotaCode", "名称", null, [], Rule.createSingleRules(),false,null,null,true,"input"))
      _self.tableHeadDatas.push(TableHeadData.createTableHeadData("type", "类型", null, [{
        value: "1",
        label: "类型1"
      }, {value: "2", label: "类型2"}], Rule.createSingleRules()))
      _self.tableHeadDatas.push(TableHeadData.createTableHeadData("creator", "创建人",null,null,null,false,null,null,true,"input"))
      _self.tableHeadDatas.push(TableHeadData.createTableHeadData("createTime", "创建时间",null,null,null,false,dateTimeFormate,null,true,"time"))
    },
    /* 方法 */
    methods: {


    }
  }
</script>

<style>
  .line {
    text-align: center;
  }

  .el-table .cell {
    text-align: center;
    white-space: pre-line; /*保留换行符*/
  }

  .pager {
    text-align: right;
  }
</style>

MyTablePage模板:


<!--
  陈岳 
  el-ui表格封装组件
  see:  表格中集成表单,并可进行有效性检查
  version: 1.0  2019-11-28 周四 22:14   init
  version: 1.0  2019-12-02 周一 16:47   新增可用设置和添加默认数据
-->
<template>
  <div>
    <!--    <div>
          <el-button type="success" size="mini" align="right" @click="insert" style="float:right; margin-right:10px;">保存
          </el-button>

              <el-button type="primary" size="mini" align="left" @click="addLine" style="float:right; margin-right:20px;"  v-if="noShowBotton('append')>添加
    </el-button>

          <el-button type="primary" size="mini" align="left" @click="addLine" style="float:right; margin-right:10px;">添加
          </el-button>
        </div>-->
    <my-search :search-datas="searchDatas" @search="search"></my-search>

    <el-button icon="el-icon-circle-plus-outline" type="primary" size="mini" align="left" @click="addLine"
               style="float:right; margin-right:20px;" v-if="noShowBotton('append')">新增
    </el-button>

    <el-form :model="formData" ref="formData" size="large" :rules="rules">
      <!--表头-->
      <el-table :data="formData.ftDatas" style="width: 100%;">
        <el-table-column
          v-for="head in ftHeadDatas"
          :key="head.value"
          :label="head.label"
          :width="head.width"
          :prop="head.value"
          v-if="head&&head.label&&head.show"
        >

          <template slot-scope="scope">
            <el-form-item :prop="'ftDatas.' + scope.$index + '.'+head.value" :rules="rules[head.value]"
                          ref="scope.row">
              <span v-if="!head.edit && !head.options">{{scope.row[head.value]|format(head.format)}}</span>
              <span v-else-if="!head.edit && head.options">{{scope.row[head.value]|showLabel(head.options)}}</span>
              <el-input size="small"
                        v-model.trim="scope.row[head.value]"
                        v-if="head.edit==EDIT.input"
                        :disabled="typeof (head.disabled) !='string'?head.disabled:exectDisable(scope,head.disabled)"
              ></el-input>
              <el-select size="small"
                         v-model.trim="scope.row[head.value]"
                         v-else-if="head.edit==EDIT.select"
                         :disabled="typeof (head.disabled) !='string'?head.disabled:exectDisable(scope,head.disabled)"
              >
                <el-option
                  v-for="option in head.options"
                  :key="option.value"
                  :label="option.label"
                  :value="option.value"
                />
              </el-select>
              <el-radio-group v-else-if="head.edit==EDIT.radio" v-model.trim="scope.row[head.value]"
                              :disabled="typeof (head.disabled) !='string'?head.disabled:exectDisable(scope,head.disabled)"
                              v-for="radioValue in head.options" :key="radioValue.label">
                <el-radio :label="radioValue.value">{{radioValue.label}}</el-radio>
              </el-radio-group>
              <el-input size="small" type="textarea"
                        v-model.trim="scope.row[head.value]"
                        v-else-if="head.edit==EDIT.textarea" placeholder="请输入内容" :rows="5"
                        :disabled="typeof (head.disabled) !='string'?head.disabled:exectDisable(scope,head.disabled)"
              ></el-input>
            </el-form-item>

          </template>
        </el-table-column>
        <el-table-column label="操作" fixed="right" min-width="218">
          <template slot-scope="scope">
            <el-button type="primary" size="mini" align="left" @click="addLine" v-if="noShowBotton('add')">添加
            </el-button>
            <el-button @click="handleDetail(scope.row)" size="mini" v-if="noShowBotton('edit')">编辑</el-button>
            <el-button type="danger" @click="handleDelete(scope.$index,scope.row)" size="mini"
                       v-if="noShowBotton('delete')&& deleteDisabled">删除
            </el-button>
          </template>
        </el-table-column>
      </el-table>
    </el-form>

    <!--<child-component ref="child"></child-component>-->
    <my-pagination :count="count" @current-page="handleCurrentPage" v-if="isPagination"></my-pagination>

    <el-button icon="el-icon-refresh" size="medium" align="right" @click="refresh"
               style="float:right; margin-right:20px;position:absolute; bottom:10px;right: 0"
               v-if="noShowBotton('refresh')">重置
    </el-button>
    <el-button type="primary" size="medium" align="right" @click="insert"
               style="float:right; margin-right:20px;position:absolute; bottom:10px; right: 120px;"
               v-if="noShowBotton('save')">保存
    </el-button>

    <!-- 放置子组件的容器-->
    <div ref="childContext">

      <!--<div v-if="!childs">加载中...</div>-->
      <!--<div v-else-if="childs && childs.length === 0">没有组件</div>-->
    </div>
    <!-- 放置子组件的容器-->
    <div ref="addChildContext">

      <!--<div v-if="!childs">加载中...</div>-->
      <!--<div v-else-if="childs && childs.length === 0">没有组件</div>-->
    </div>
  </div>

</template>
<script>
  //组件
  import MyPagination from "@/components/commonComponents/MyPagination"
  import MySearch from '@/components/commonComponents/MySearch'

  import Vue from 'vue'

  export default {
    name: "MyTablePage",
    // components: {"my-pagination": MyPagination},
    components: {"my-pagination": MyPagination, MySearch},
    filters: {
      format(data, funFormat) {
        if (!funFormat || typeof funFormat != "function") return data
        return funFormat(data)
      },
      showLabel(data, options) {
        if (Array.isArray(options)) {
          for (let item of options) {
            if (item.value == data) return item.label
          }
        }

      }
    },
    /* 父组件传递数据 */
    props: {
      isPagination: {
        type: Boolean,
        default: false
      },
      /*表头数据*/
      tableHeadDatas: {
        type: Array,
        required: true
      },

      /*表格数据请求*/
      tableDataRequest: {
        type: Function,//Promise
        required: true
      },

      /*表格数据请求参数*/
      tableDataRequestParams: {
        type: Object,
        required: true
      },

      /*向后台保存请求的request对象*/
      insertRequest: {
        type: Function,//Promise
        default: {}
      },

      /*详情按钮*/
      detail: {
        type: String,//Promise
        default: ""
      },

      /*不展示的按钮*/
      //["add","edit","delete","refresh","save"]
      //添加,编辑,删除        重置,保存
      noShowBottons: {
        type: Array, default: () => {
          return ["edit", "append"]
        }
      },

      detailed: Boolean,
      deleted: Boolean,
      childComponentPath: {
        type: String
      },
      addComponentPath: String,
      throwParent: Boolean
    },
    /* 数据 */
    data() {
      return {
        searchDatas: [],
        //验证规则
        rules: [],
        // list数据
        formData: {
          ftDatas: []
        },

        ftDataParams: this.tableDataRequestParams,

        ftHeadDatas: this.tableHeadDatas,
        //删除对象集合
        deletes: [],

        pageNumber: 1,//跳转到的页数
        pageSize: 10,//每页展示的记录数
        count: 0,
        childComponent: {},
        Component: {},
        addComponent: {},
        row: {},
        deleteDisabled: true
      }
    },
    provide () {
      return {
        parentRefresh: this.refresh()
      }
    },
    /* 计算方法 */
    computed: {},
    watch: {     //监听value的变化,进行相应的操作即可
      tableHeadDatas: function (newValue, oldValue) {
        // console.log("tableHeadDatas oldValue = "+ oldValue)
        this.ftHeadDatas = newValue
        // console.log("tableHeadDatas newValue = "+ newValue)
      },
      tableDataRequestParams: function (newValue, oldValue) {
        console.log("监听 tableDataRequestParams newValue = " + newValue)
        this.ftDataParams = newValue

        this.refresh()
        // console.log("tableHeadDatas newValue = "+ newValue)
      }
    }
    ,
    created() {
      console.log("created =========")
      let _self = this
      if (_self.childComponentPath) {
        _self.registerComponent(_self.childComponentPath).then(Component => {

          _self.childComponent = new Component({propsData:{parentRefresh: _self.refresh}})

          _self.childComponent.$mount(_self.$refs.childContext)

        })
      }

      if (_self.addComponentPath) {
        _self.registerComponent(_self.addComponentPath).then(Component => {

          _self.addComponent = new Component({propsData:{parentRefresh: _self.refresh}})

          _self.addComponent.$mount(_self.$refs.addChildContext)

        })
      }


      if (_self.tableHeadDatas && Array.isArray(_self.tableHeadDatas)) {
        _self.searchDatas = _self.tableHeadDatas.filter(item => {
          return item.search
        })
        // console.log("searchDatas = " + _self.searchDatas.length)
        // console.log("tableHeadDatas = " + _self.tableHeadDatas.length)
      }

      _self.rules = _self.getRules()
      if (_self.isPagination && _self.ftDataParams.page) {
        _self.pageNumber = _self.ftDataParams.page.pageNumber
        _self.pageSize = _self.ftDataParams.page.pageSize
      }
      _self.refresh()
    }
    ,
    methods: {
      refresh() {
        let _self = this

        console.log("刷新请求 : "+"requestparams = " + ((_self.ftDataParams||{}).detailDMO||{}).mainConfId)


        _self.tableDataRequest(_self.ftDataParams).then(response => {

          if (response.code === '0') {
            _self.formData.ftDatas = []
            if (response.data.length) {
              _self.formData.ftDatas = response.data
            } else {
              if (response.data.result && response.data.result.length > 0) {
                // console.log("result = "+response.data.result.length)
                _self.formData.ftDatas = response.data.result
              } else {
                // console.log("add = ")
                if (!_self.noShowBotton('append')) {
                  _self.addLine()
                }

              }
            }

            _self.deleteDisabled = !(_self.formData.ftDatas.length == 1)
            _self.count = response.data.count
          }
        });
      },

      getRules() {
        let _self = this
        let rules = {}
        _self.ftHeadDatas.forEach((item, index) => {
          if (item && item.rule && item.rule.length > 0) {
            item.rule.forEach(ruleItem => {
              if (ruleItem && !ruleItem.message) {//设置默认验证提醒内容
                if (ruleItem.edit == "input") {
                  ruleItem.message = "请输入" + item.label
                } else {
                  ruleItem.message = "请选择" + item.label
                }
              }
            });
            rules[item.value] = item.rule
          }
        });
        return rules
      }
      ,
      addLine() { //添加行数
        let _self = this
        let newLine = {}

        _self.tableHeadDatas.forEach(item => {
          if (item) {
            if (item.defaults) {
              for (let key in item.defaults) {
                newLine[key] = item.defaults[key]
              }
            } else {
              newLine[item.value] ? null : newLine[item.value] = null
            }
          }

        })

        if (_self.addComponentPath) {
          // console.log("this.addComponentPath=" + _self.addComponentPath)
          _self.addComponent.row = {}
          _self.addComponent.row = newLine
        } else {
          _self.formData.ftDatas.push(newLine)
          _self.deleteDisabled = !(_self.formData.ftDatas.length == 1)
        }
      }
      ,
      insert() {
        let _self = this
        _self.$confirm('是否保存此数据?', '提示:', {
          confirmButtonText: '确定',
          cancelButtonText: '取消',
          type: 'warning'
        }).then(() => {
          _self.$refs.formData.validate(valid => {
            if (valid) {
              // console.log(" data = " + _self.formData.ftDatas.length)
              // console.log(" deletes = " + _self.deletes.length)
              let models = {
                data: _self.formData.ftDatas,
                deletes: _self.deletes,
              }
              if (_self.throwParent) {
                // console.log("由父类保存数据")
                _self.$emit('sendList', models)
              } else {
                _self.insertRequest(models).then(response => {
                  if (response.code === '0') {
                    _self.$message({
                      duration: 2000,
                      showClose: true,
                      message: response.msg,
                      type: 'success'
                    });
                    _self.refresh()
                  } else if (response.code === '1') {
                    _self.$message.error(response.msg)
                  } else {
                    _self.$message.error('保存失败')
                  }
                }).catch(() => {
                  _self.$message.error('保存失败')
                });
              }

            } else {
              _self.$confirm('请检查数据格式', '提示:数据校验不成功', {
                confirmButtonText: '确定',
                cancelButtonText: '取消',
                type: 'warning'
              });
            }
          });


        });
      }
      ,
      handleDelete(index, row) {
        let _self = this
        if (row && row.id) {
          console.log("id = " + row.id)
          _self.deletes.push(row)
        }
        _self.formData.ftDatas.splice(index, 1)
        _self.deleteDisabled = !(_self.formData.ftDatas.length == 1)
      }
      ,

      handleDetail(row) {
        this.childComponent.row = {}
        this.childComponent.row = row
      },

      exectDisable(scope, statement) {
        if (statement == "scope.row.getWay!= 'EVENT' || scope.row.getWay!= 'REQ'") {
          console.log("eval(statement) = " + eval("scope.row.getWay== 'EVENT' || scope.row.getWay== 'REQ'"))
          // console.log("eval(scope.row.getWay!= 'EVENT') = "+eval("scope.row.getWay!= 'EVENT'"))
          // console.log("eval(scope.row.getWay!= 'REQ') = "+eval("scope.row.getWay!= 'REQ'"))
        }
        return eval(statement)
      },

      handleCurrentPage(currentPage) {
        let _self = this
        _self.pageNumber = currentPage
        if (!_self.ftDataParams.page) {
          _self.ftDataParams.page = {}
          _self.ftDataParams.page.pageNumber = currentPage
        } else {
          _self.$set(_self.ftDataParams.page, "pageNumber", currentPage)
        }
        _self.refresh()
      },

      noShowBotton(button) {
        let _self = this
        return !_self.noShowBottons.some(item => {
          return item == button
        })
      },

      /**
       *@desc 统一加载注册组件资源
       *@return {Promise}
       */
      registerComponent(componentName) {
        console.log("@/views/" + componentName)
        return import("@/views/" + componentName).then(component => {


          return Vue.extend(component.default);
        });

      },

      search(param) {
        console.log("MyTablePage")
        for(let key in param){
          console.log("key = "+key +", param = "  + param[key])
        }
        let _self = this
        let keys = Object.keys(_self.ftDataParams)
        if (keys.length <= 2) {
          keys.forEach(item => {
            if(item != "page")Object.assign(_self.ftDataParams[item], param)
          })
        }
        _self.refresh()

      }
    }
  }
</script>
<style>
  .el-form-item__error {
    position: unset
  }
</style>

表单上方的搜索框

<template>
  <el-form :inline="true" :model="queryForm" ref="queryForm" size="mini">
    <transition name="fade" v-if="searchDatas&&searchDatas.length>0">
      <div>
              <el-form-item
                            v-for="head in searchDatas"
                            :key="head.value"
                            :label="head.label"
                            :prop="head.value"
              >
                <el-input size="small" v-model.trim="queryForm[head.value]"
                          v-if="head.search=='input'"
                ></el-input>
                <el-select size="small" v-model.trim="queryForm[head.value]"
                           v-if="head.search=='select'">
                  <el-option
                    v-for="option in head.options"
                    :key="option.value"
                    :label="option.label"
                    :value="option.value"/>
                </el-select>
                <el-radio-group v-if="head.search=='radio'" v-model.trim="queryForm[head.value]"
                                v-for="radioValue in head.options" :key="radioValue.label">
                  <el-radio :label="radioValue.value">{{radioValue.label}}</el-radio>
                </el-radio-group>

                <el-date-picker v-if="head.search=='time'" :picker-options="pickerOptions2" v-model="queryForm[head.value+'Range']"
                                style="width: 375px" type="datetimerange" range-separator="至" start-placeholder="开始日期" @change="timeChange(head.value)"
                                end-placeholder="结束日期">
                </el-date-picker>
              </el-form-item>


        <div style="float:right;">
          <el-form-item>
            <el-button type="primary" icon="el-icon-search"  @click="search">查询</el-button>
            <!--<el-button type="primary" icon="el-icon-search" @click="onSearchClicked">查询</el-button>-->
            <el-button icon="el-icon-refresh" @click="resetForm">重置</el-button>
            <!--<el-button icon="el-icon-refresh" @click="compensate">补偿</el-button>-->
          </el-form-item>
        </div>
      </div>
    </transition>

  </el-form>
</template>

<script>
  import {dateTimeFormate} from '@/utils/dateUtils'
    export default {
        name: "MySearch",
      props:{
        searchDatas:Array
      },
      data(){
          return {
            pickerOptions2: {
              shortcuts: [{
                text: '最近一周',
                onClick(picker) {
                  const end = new Date()
                  const start = new Date()
                  start.setTime(start.getTime() - 3600 * 1000 * 24 * 7)
                  picker.$emit('pick', [start, end])
                }
              }, {
                text: '最近一个月',
                onClick(picker) {
                  const end = new Date()
                  const start = new Date()
                  start.setTime(start.getTime() - 3600 * 1000 * 24 * 30)
                  picker.$emit('pick', [start, end])
                }
              }, {
                text: '最近三个月',
                onClick(picker) {
                  const end = new Date()
                  const start = new Date()
                  start.setTime(start.getTime() - 3600 * 1000 * 24 * 90)
                  picker.$emit('pick', [start, end])
                }
              }]
            },

            queryForm:{}
          }
      },
      created() {

      },
      methods:{
        resetForm() {
          let _self = this
          _self.$refs['queryForm'].resetFields()
          for (let key in _self.queryForm){
            console.log("key = "+key)
            _self.queryForm[key] = null
          }
        },
        search(){
          let _self = this

          _self.$emit("search",_self.queryForm)
        },
        timeChange(value){
          let _self = this
          console.log("timeChange = " + value)
          if (_self.queryForm[value+"Range"]) {
            _self.queryForm[value+"Begin"] = dateTimeFormate(_self.queryForm[value+"Range"][0])
            _self.queryForm[value+"End"] = dateTimeFormate(_self.queryForm[value+"Range"][1])
          }

        }
      }
    }
</script>

<style scoped>

</style>

分页组件:

<!--
  陈岳  88477865
  el-ui分页封装组件
  version: 1.0  2019-12-5 周四 22:14   init
-->
<template>
  <div>
    <el-pagination
      background
      @current-change="handleCurrentChange"
      layout="total,prev, pager, next,jumper"
      :total="total">
    </el-pagination>
  </div>
</template>
<script>
  export default {
    name: "MyPagination",
    components: {},
    /* 父组件传递数据 */
    props: {
      /*数据总数*/
      count: {
        type: Number,
        required: true
      },
    },
    /* 数据 */
    data() {
      return {
        total:this.count
      }
    },
    /* 计算方法 */
    computed: {},
    watch: {     //监听value的变化,进行相应的操作即可
      count: function (newValue, oldValue) {
        this.total = newValue
      }
    },
    created() {
    }
    ,
    methods: {
      //当前页变动   currentPage 改变时会触发
      handleCurrentChange(currentPage){
        this.$emit('current-page', currentPage)
      }

    }
  }
</script>
<style>
  .el-form-item__error {
    position: unset
  }
</style>



使用到的对象:

export class TableHeadData{
  defaults={}//不展示的必备值{key:value} 数据库字段名:值
  constructor(value,label,edit,options,rules,disabled,format,width=160,show=true,search=false){
    this.value=value//后台对象属性
    this.label=label//表头显示数据
    this.edit=edit//展示方式 可选值=> input:输入框,select:下拉框,radio:单选
    this.options=options//当edit=select或radio时的可选值,是Option对象集合
    this.rule=rules//Rule对象集合
    this.disabled=disabled//是否可用
    this.format = format//展示文字格式
    this.width=width//宽度
    this.show=show//是否显示
    this.search=search//是否需要再列表上创建搜索表单
  }


  static createTableHeadData(value,label,edit,options,rules,disabled=false,format,width,show,search) {
    if ((edit=="select" || edit=="radio") && rules&& rules.length==1&&rules[0].trigger=="blur"){

      console.log("rules change")
      rules.push(Rule.createSingleRules("change"))
    }
    return new TableHeadData(value,label,edit,options,rules,disabled,format,width,show,search)
  }
  static createDefaultNoShow(defaults) {
    let defaultValues = new TableHeadData()
    defaultValues.defaults = defaults
    return defaultValues
  }
}

export function Option(label,value) {
  this.label=label//显示内容
  this.value=value//选中值
}

export class Rule{ //有效性检测
  constructor(trigger,required,message){
    this.trigger=trigger//触发事件
    this.required= required//是否必须
    this.message=message//提示消息(可省略)
  }
  static createSingleRules(trigger="blur",required=true,message){
    return [new Rule(trigger,required,message)]
  }
}

export function TableData() {}//表格展示数据   tableHeadDatas.value=后台对象属性对应值

export const TABLE_TYPE={
  input:"input",
  select:"select",
  radio:"radio",
  textarea:"textarea"
}
Object.freeze(TABLE_TYPE)


第二个版本:变为自定义标签格式

版本二将组件定义为自定义组件,类似于element-ui,命名为my-ui
使用方式改为:只需要配置表格请求函数,请求参数,就可以展示出表格,当参数变化时,表格就会刷新

<template>
    <div>----------------helloworld--------------------
    <my-table :table-request="tableDataRequest" :table-request-params="tableDataRequestParams">
        <my-table-column type="input" field="dcode" label=名称"></my-table-column>
        <my-table-column type="input" field="type" label=类型"></my-table-column>
        <my-table-column field="creator" label="创建人"></my-table-column>
        <my-table-column field="createTime" label="创建时间" :format="format"></my-table-column>
    </my-table></div>
</template>

<script>

    import {dateTimeFormate} from '@/utils/dateUtils'
    import {getConfigs} from '@/api/configure'
    export default {
        name: 'HelloWorld',
        components: {},
        props: {
            msg: String
        },
        data(){
            return {
                tableDataRequest: getConfigs,//function
                tableDataRequestParams: {entity: {id: 6}},//object
                format:dateTimeFormate,
            }
        }
    }
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
    h3 {
        margin: 40px 0 0;
    }

    ul {
        list-style-type: none;
        padding: 0;
    }

    li {
        display: inline-block;
        margin: 0 10px;
    }

    a {
        color: #42b983;
    }
</style>

源码的目录结构为:
封装element-ui的table和form组件
my-table组件

<template>
    <el-form :model="formData" ref="formData" size="large" :rules="rules">
        <!--表头-->
        <el-table :data="formData.ftDatas" style="width: 100%;">
            <slot></slot>
        </el-table>
    </el-form>


</template>

<script>
    export default {
        name: 'MyTable',

        provide() {
            return {
                myTable: this
            };
        },

        props: {
            tableRequest: Function,
            tableRequestParams: Object,
            saveRequest: Function,
            isPagination: Boolean
        },

        data() {
            return {
                requestParams: this.tableRequestParams,

                rules: {},
                formData: {
                    tableData: []
                },

                count:0,
            }

        },

        watch: {
            tableRequestParams: function (newValue) {
                this.requestParams = newValue
                this.refresh()
            }

        },

        created() {
            this.refresh()
        },

        methods: {
            refresh() {
                console.log("刷新 == ")
                let _self = this
                _self.tableRequest(_self.requestParams).then(response => {
                    if (response.code === '0') {
                        _self.formData.tableData = []
                        if (response.data.length) {
                            _self.formData.tableData = response.data
                            if (isPagination) _self.count = response.data.count
                        } else {
                            if (response.data.result && response.data.result.length > 0) {
                                _self.formData.tableData = response.data.result
                                if (isPagination) _self.count = response.data.result.count
                            } else {
                                //todo 空白添加默认行

                            }
                        }
                    }
                    _self.deleteDisabled = !(_self.formData.ftDatas.length == 1)
                })
            },

            addRule(rule) {
                this.rules.push(rule)
            }
        }
    }

</script>
<style>
</style>

my-table-column组件:

<template>
    <el-table-column
            :label="label"
            :width="width"
            :prop="field"
            v-if="!noShow"
    >
        <template slot-scope="scope">
            <el-form-item :prop="field" >
                <span v-if="!type && !options">{{scope.row[field]|format(format)}}</span>
                <span v-else-if="!type && options">{{scope.row[field]|showLabel(options)}}</span>
                <el-input size="small"
                          v-model="scope.row[field]"
                          v-if="type==TYPE.input"
                          :disabled="disabled =='true'?true:exectDisable(scope,disabled)"
                ></el-input>
                <el-select size="small"
                           v-model="scope.row[field]"
                           v-else-if="type==TYPE.select"
                           :disabled="disabled =='true'?true:exectDisable(scope,disabled)"
                >
                    <el-option
                            v-for="option in options"
                            :key="option.value"
                            :label="option.label"
                            :value="option.value"
                    />
                </el-select>
                <el-radio-group v-else-if="type==TYPE.radio" v-model="scope.row[field]"
                                :disabled="disabled =='true'?true:exectDisable(scope,disabled)"
                                v-for="radioValue in options" :key="radioValue.label">
                    <el-radio :label="radioValue.value">{{radioValue.label}}</el-radio>
                </el-radio-group>
                <el-input size="small" type="textarea"
                          v-model.trim="scope.row[head.value]"
                          v-else-if="type==TYPE.textarea" placeholder="请输入内容" :rows="5"
                          :disabled="disabled =='true'?true:exectDisable(scope,disabled)"
                ></el-input>
            </el-form-item>
        </template>
    </el-table-column>


</template>

<script>
    export default {
        name: 'MyTableColumn',

        inject: ['myTable'],

        filters: {
            format(data, funFormat) {
                if (!funFormat || typeof funFormat != "function") return data
                return funFormat(data)
            },
            showLabel(data, options) {
                if (Array.isArray(options)) {
                    for (let item of options) {
                        if (item.value == data) return item.label
                    }
                }
            }
        },

        props: {
            type: String,//column的展示方式 可选项:[null,"input","select","radio","textarea"]
            options: {
                type: Array,
                default: () => {
                    return []
                }
            },//select和radio的选项
            field: String,//字段对应名称
            label: String,// 显示表头文字
            rules: {
                type: Array,
                default: () => {
                    return []
                }
            },// 判断规则
            width: {type: Number, default: 160},// 列宽
            disabled: String,// 是否可用
            noShow: Boolean,// 是否显示
            format: Function
        },

        data() {
            return {}
        },

        created() {
            let _self = this
            let field = _self.field


        },

        methods: {
            exectDisable(scope, statement) {
                return eval(statement)
            },
        }
    }
</script>

<style scoped>

</style>