乐趣区

关于vue.js:vueelement-动态表格组件

需要

1. 表头数据不固定
2. 表头数据多层级
3. 表格跨行跨列
4. 表格可编辑
5. 编辑反对根本表单框

子组件代码

dynamic-header.vue

<template>
  <div>
    <el-form size="medium" class="horizontal" inline>
      <slot name="search"></slot>
    </el-form>
    <div class="title" v-if="title">{{title}}</div>
    <el-table
      v-loading="listLoading"
      :data="list"
      :stripe="true"
      class="flexible"
      :border="true"
      :span-method="arraySpanMethod"
      style="overflow: auto"
      :height="height"
      ref="table"
      width="100%"
    >
      <template
        v-for="(item,index) in tableHeader">
        <table-column  v-if="item.children && item.children.length" :key="Math.random()"  :coloumn-header="item"></table-column>
        <el-table-column v-else  class-name="custom"
                         :width="item.width?item.width:'auto'":fixed="item.fixed":key="Math.random()":label="item.tableHeadName"align="center">
          <template slot-scope="scope">
            <template v-if="item.isEdit">
              <el-select
                filterable
                v-if='(item.htmlType =="select"|| item.htmlType =="radio") && item.dictData'
                v-model.lazy="scope.row[item.tableFiled]">
                <el-option
                  v-for="dict in item.dictData"
                  :key="dict[item.options.value] || dict.value"
                  :label="dict[item.options.label] || dict.label"
                  :value="parseInt(dict[item.options.value] || dict.value)"
                />
              </el-select>

              <el-date-picker
                v-else-if='item.htmlType =="datetime"&& item.queryType !="BETWEEN"'clearable size="small"v-model.lazy="scope.row[item.tableFiled]"type="date"value-format="yyyy-MM-dd">
              </el-date-picker>
              <el-date-picker
                v-else-if='item.htmlType =="datetime"&& item.queryType =="BETWEEN"'v-model.lazy="scope.row[item.tableFiled]"size="small"style="width: 240px"value-format="yyyy-MM-dd"type="daterange"range-separator="-"start-placeholder=" 开始日期 "end-placeholder=" 完结日期 "
              ></el-date-picker>
              <el-input-number
                v-else-if='item.htmlType =="number"'v-model.lazy="scope.row[item.tableFiled]"
                clearable
                size="small"
              />
              <el-input
                v-else
                v-model.lazy="scope.row[item.tableFiled]"
                clearable
                size="small"
              />
            </template>
            <template v-else-if="item.template">
              {{getTemplate(item.template,scope)}}
            </template>
            <template v-else>
              <dict-tag v-if="item.dictData" :options="item.dictData" :value="scope.row[item.tableFiled]" />
              <tempalte  v-else-if="item.dictDataArray" >
                <dict-tag v-for="(it,itIndex) in item.dictDataArray"  v-if="scope.row[it.props] == it.value" :key="itIndex" :options="it.dictData" :value="scope.row[item.tableFiled]" />
              </tempalte>
              <template v-else>{{scope.row[item.tableFiled]}}</template>
            </template>
          </template>
        </el-table-column>
      </template>
      <el-table-column v-if="pageParamInfo.oper" label="操作" :key="index" fixed="right" width="150">
        <template slot-scope="scope">
          <slot name="oper" :scope="scope.row"></slot>
        </template>
      </el-table-column>
    </el-table>
    <slot name="tableFooter" :scope="pageParamInfo.req"></slot>
  </div>

</template>
<script>
  import TableColumn from './table-column'
  export default {
    props: {
      pageParamInfo: {
        type: Object,
        default(){return {}
        }
      },
      tableHeader: {
        type: Array,
        default(){return []
        }
      },
      RowRules: {
        type: Array,
        default(){return []
        }
      },
      list: {
        type: Object,
        default(){return {}
        }
      },
      title: {
        type: String,
        default: ""
      },
      listLoading: {
        type: Boolean,
        default:  false
      },
      height: {
        type: String,
        default: "70vh"
      },
    },
    // pageParamInfo 页面列表参数:url  req 等等;// tableHeader 表头信息
    components: {TableColumn,},
    data() {return {}
    },
    watch: {tableHeight(val) {this.height = val}
    },
    created() {},
    mounted() {},
    methods: {getTemplate(template,scope){return eval(template)
      },
      arraySpanMethod({row, column, rowIndex, columnIndex}) {
        let returnMap = {
          rowspan: 1,
          colspan: 1
        }
        const data = this.RowRules
        if (data instanceof Array && data.length > 0) {
          data.forEach(item => {if (item.col === (columnIndex + 1)) {if (rowIndex % item.row === 0) {
                returnMap = {
                  rowspan: item.row,
                  colspan: 1
                }
              } else {
                returnMap = {
                  rowspan: 0,
                  colspan: 0
                }
              }
            }
          })
        }
        return returnMap
      },
      // 列表
      getList() {
        this.listLoading = true
        this.$http.post(this.pageParamInfo.url, this.pageParamInfo.req).then(res => {
          this.listLoading = false
          // this.list = res.data.list
        })
      },
      // 文件上传中解决
      handleExceed(event, file, fileList) {this.upload.isUploading = true},
      // 文件上传胜利解决
      handleSuccess(response, file, fileList) {
        this.upload.open = false
        this.upload.isUploading = false
        this.$refs.upload.clearFiles()
        this.$alert(response.message, '导入后果', {dangerouslyUseHTMLString: true,})
        this.getList()},
      // 重置
      reset() {
        /* this.listLoading = true
         this.$http.post('busprojecttask/findTaskList', this.req).then(res => {
           this.listLoading = false
            this.getList(this.req.MONTH)
         })*/
      },
      // 批改
      save() {
        /* this.listLoading = true
          this.$http.post('busprojecttask/findTaskList', this.req).then(res => {
            this.listLoading = false
             this.getList(this.req.MONTH)
          })*/
      }
    }
  }
</script>

<style  lang="scss" scoped>
  h1{
    color: black !important;
    text-align: center;
    padding: 20px;
  }
  table{margin-top: 20px;}
  .tableClass{
    ::v-deep .el-table__fixed{height: 100% !important;   // 设置高优先,以笼罩内联款式}
  }
</style>

table-column.vue

<template>
  <el-table-column :label="coloumnHeader.tableHeadName" :prop="coloumnHeader.tableFiled" align="center">
    <template v-for="item in coloumnHeader.children">
      <tableColumn v-if="item.children && item.children.length" :key="Math.random()"  :coloumn-header="item"></tableColumn>
      <el-table-column :fixed="item.fixed" :width="item.width?item.width:'auto'"v-else :key="Math.random()":label="item.tableHeadName":prop="item.tableFiled"align="center">
        <template slot-scope="scope">
          <template v-if="item.isEdit">
            <el-select
              v-if='(item.htmlType =="select"|| item.htmlType =="radio") && item.dictData'
              v-model.lazy="scope.row[item.tableFiled]">
              <el-option
                v-for="dict in item.dictData"
                :key="dict.value"
                :label="dict.label"
                :value="parseInt(dict.value)"
              />
            </el-select>
            <el-date-picker
              v-else-if='item.htmlType =="datetime"&& item.queryType !="BETWEEN"'clearable size="small"v-model.lazy="scope.row[item.tableFiled]"type="date"value-format="yyyy-MM-dd">
            </el-date-picker>
            <el-date-picker
              v-else-if='item.htmlType =="datetime"&& item.queryType =="BETWEEN"'v-model.lazy="scope.row[item.tableFiled]"size="small"style="width: 240px"value-format="yyyy-MM-dd"type="daterange"range-separator="-"start-placeholder=" 开始日期 "end-placeholder=" 完结日期 "
            ></el-date-picker>
            <el-input-number
              v-else-if='item.htmlType =="number"'v-model.lazy="scope.row[item.tableFiled]"
              clearable
              size="small"
            />
            <el-input
              v-else
              v-model.lazy="scope.row[item.tableFiled]"
              clearable
              size="small"
            />
          </template>
          <template v-else-if="item.template">
            {{getTemplate(item.template,scope)}}
          </template>
          <template v-else>
            <dict-tag v-if="item.dictData" :options="item.dictData" :value="scope.row[item.tableFiled]" />
            <tempalte  v-else-if="item.dictDataArray" >
              <dict-tag v-for="(it,itIndex) in item.dictDataArray"  v-if="scope.row[it.props] == it.value" :key="itIndex" :options="it.dictData" :value="scope.row[item.tableFiled]" />
            </tempalte>
            <template v-else>{{scope.row[item.tableFiled]}}</template>
          </template>
        </template>
      </el-table-column>
    </template>
  </el-table-column>
</template>

<script>
export default {
  name: 'TableColumn',
  props: {
    coloumnHeader: {
      type: Object,
      required: true
    }
  }
}
</script>

<style scoped>

</style>

父组件

list 为表格数据,tableHeader 为表头数据

<template>
  <dynamicHeaderEdit
            :tableHeader="tableHeader"
            :list="list"
            ref="table">
          </dynamicHeaderEdit>
</template>
退出移动版