自定义表格

这个表格写了很久了,最近才整理。
自定义表格可以根据数据自动生成表头,多级表头,列
约定的数据格式如下:

/** 数据格式
   *
   headList:[
   {
     prop:"date",
     label:"日期",
     width:"150",
     url:'',
     path:'',
     yl:'',
     children:[]
   },
   {
     prop:"",
     label:"地址",
     width:"",
     url:'',
     path:'',
     yl:'',
     children:[{
       prop:"province",
       label:"省份",
       width:"120",
       url:'',
       path:'',
       yl:'',
     },
       {
         prop:"zip",
         label:"邮编",
         width:"120",
         url:'',
         path:'',
         yl:'',
       }
     ]
   }
   ],
   tableData: [{
        date: '2016-05-03',
        name: '王小虎',
        province: '上海',
        city: '普陀区',
        address: '上海市普陀区金沙江路 1518 弄',
        zip: 200333
      }]
   *
   */

HeadTable.vue

<template>
  <el-table
    v-loading.iTable="loading"
    :data="tableDatas"
    :row-style="selectedRowStyle"
    :row-class-name="rowStyle"
    style="width: 100%"
    :height="height"
    stripe
    border
    @row-click="scaleRow"
    @row-dblclick="dblclick"
    @sort-change="sortchange"
  >
    <!--:span-method="objectSpanMethod"-->
    <template>
      <el-table-column
        v-for="(column,index) in headList"
        :key="index"
        :label="column.label"
        align="center"
        :fixed="column.gd && column.gd.indexOf(column.prop)>-1 "
        :width="column.width"
        show-overflow-tooltip
        :prop="column.prop"
        :sortable="(!(column.children && column.children.length !== 0 || column.label === '序号' || column.label === '操作' || column.label === '得分组成'))?'custom':false"
      >
        <template v-if="column.children && column.children.length !== 0">
          <el-table-column
            v-for="(column1,index1) in column.children"
            :key="index1"
            align="center"
            :label="column1.label"
            :width="column1.width"
            show-overflow-tooltip
            :prop="column1.prop"
            sortable="custom"
          >
            <template slot-scope="scope">
              <div v-if="(column1.hasOwnProperty('path')&&column1.path&&column1.path.length!==0)||(column1.hasOwnProperty('url')&&column1.url&&column1.url.length!==0)">
                <el-button
                  style="border: none;padding: 0;"
                  :style="[{color:column1.higlight!=='#464646'?column1.higlight:''}]"
                  class="cell_span"
                  :class="clickedRow==scope.row.index?'scale-row':''"
                  @click="toputh(column1,scope.row)"
                >{{ scope.row[(column1.prop+(column1.yl?column1.yl:''))] }}</el-button>
              </div>
              <div v-else>
                <span :style="[{color:column1.higlight}]">{{ scope.row[(column1.prop+(column1.yl?column1.yl:''))] }}</span>
              </div>
            </template>
          </el-table-column>
        </template>
        <template slot-scope="scope">
          <div v-if="(column.hasOwnProperty('path')&&column.path&&column.path.length!==0)||(column.hasOwnProperty('url')&&column.url&&column.url.length!==0)">
            <el-button
              style="border: none;padding: 0;"
              :style="[{color:column.higlight!=='#464646'?column.higlight:''}]"
              class="cell_span"
              :class="clickedRow==scope.row.index?'scale-row':''"
              @click="toputh(column,scope.row)"
            >{{ scope.row[(column.prop+(column.yl?column.yl:''))] }}</el-button>
          </div>
          <div v-else>
            <span :style="[{color:column.higlight}]">{{ scope.row[(column.prop+(column.yl?column.yl:''))] }}</span>
          </div>
        </template>
      </el-table-column>
    </template>>
  </el-table>
</template>

<script>
/**
   * @author wangligang
   * @date 2020/8/4
   * @Description:
   * @update by: 表格组件
   *
   *
   /

const evalData = (data) => {
  const tmp = []
  Array.from(data).forEach((row, index) => {
    if (!Array.isArray(row)) {
      tmp.push({ no: index + 1, ...row })
    } else {
      //
    }
  })
  return tmp
}

export default {
  props: {
    tableData: {
      type: [Array, Object],
      required: true
    },
    headList: {
      type: Array,
      default: () => []
    },
    query: {
      type: Object,
      default: () => {}
    },
    height: {
      type: String,
      default: () => 'calc(100vh - 220px)'
    },
    loading: {
      type: Boolean,
      default: () => false
    }
  },
  data() {
    return {
      clickedRow: -1,
      spanArr: [],
      pos: 0
    }
  },
  computed: {
    // 格式化表格数据
    tableDatas: function() {
      const tmp = !Array.isArray(this.tableData) ? [this.tableData] : this.tableData
      this.getSpanArr(evalData(tmp))
      return evalData(tmp)
    }
  },
  methods: {
    getSpanArr(data) {
      this.spanArr = []
      this.pos = 0
      for (var i = 0; i < data.length; i++) {
        if (i === 0) {
          this.spanArr.push(1)
          this.pos = 0
        } else {
          // 判断当前元素与上一个元素是否相同
          if (data[i].nsrsbh && data[i].nsrsbh === data[i - 1].nsrsbh) {
            this.spanArr[this.pos] += 1
            this.spanArr.push(0)
          } else {
            this.spanArr.push(1)
            this.pos = i
          }
        }
      }
    },
    dblclick(row, column, event) {
      let data = {}
      let Y = false
      this.headList.map(item => {
        if (item.label === '操作') {
          data = item
          Y = true
        } else if (item.url && item.url.length !== 0) {
          Y = true
        }
      })
      if (Y) {
        this.$emit('dblclick', row, data)
      }
    },
    toputh(row, data) {
      if (row.path && row.path.length !== 0) {
        this.$router.push({ path: row.path, query: { ...this.query }})
      } else if (row.url && row.url.length !== 0) {
        this.$emit('urlClick', row, data)
      }
    },
    scaleRow(row) {
      this.clickedRow = row.index
    },
    rowStyle({ rowIndex }) {
      if (this.clickedRow === rowIndex) {
        return 'scale-row'
      }
    },
    selectedRowStyle({ row, rowIndex }) {
      row.index = rowIndex
    },
    sortchange({ column, prop, order }) {
      this.$emit('sortchange', { column, prop, order })
    },
    objectSpanMethod({ row, column, rowIndex, columnIndex }) {
      if (!row.nsrsbh) {
        this.obj = { row, column, rowIndex, columnIndex }
        return {
          rowspan: 1,
          colspan: 1
        }
      }
      if (row.columnspan.indexOf(column.property) > -1) {
        const _row = this.spanArr[rowIndex]
        const _col = _row > 0 ? 1 : 0
        return {
          rowspan: _row,
          colspan: _col
        }
      }
    }
  }
}
</script>
<style lang="scss">
  .el-table{
    .scale-row{
      font-size:15px;
      font-weight:600;
      background-color:#f5f7fa;
      transition:all .3s ease-in-out;
    }
    .bg-disable{
      background:rgba(224,224,224,.3);
    }
    .bg-active{
      background: #bccbe4;
    }
  }
</style>

使用方式
引入组件

<HeadTable :headList="headList" :tableData="tableData"></HeadTable>

上一篇:socket.io中emit和on的用法【转】


下一篇:优化接口性能 - 单表优化sql查询语句