vue element-ui 可行列转置表格组件

605 阅读1分钟

为什么要写:

数据展示模式不清晰, 时而按系统展示,时而按范围展示;

转置表格.gif

实现:

<template>
  <div class="double-col-table">
    <v-table :cols="column" :data="showData" :height="tableHeight"></v-table>
  </div>
</template>
​
<script>
import VTable from './VTable.vue';
​
export default {
  name: 'DoubleColTable',
  components: { VTable },
  props: {
    xKey: {
      type: Object,
      required: true
    },
    yKey: {
      type: Object,
      required: true
    },
    xCols: {
      type: Array,
      required: true
    },
    yCols: {
      type: Array,
      required: true
    },
    data: {
      type: Array,
      required: true
    },
    height: {
      type: [String, Number],
    },
    reversed: {
      type: Boolean,
      default: false,
    }
  },
  data() {
    return {
      innerReversed: this.reversed,
      maxHeight: 500,
    }
  },
  computed: {
    yColsObj() {
      return this.yCols.map((i, idx) => ({ prop: `${this.yKey.prop}${idx + 1}`, label: i }))
    },
    column() {
      const { innerReversed } = this;
      const xKey = innerReversed ? this.yKey : this.xKey;
      const yKey = innerReversed ? this.xKey : this.yKey;
​
      let cols = [
        { prop: yKey.prop, label: `${yKey.label} \ ${xKey.label} ` }
      ];
​
      if(!innerReversed) {
        cols = cols.concat(this.xCols)
      }
      else {
        cols = cols.concat(this.yColsObj)
      }
​
      return cols;
    },
    filterData() {
      return this.data.map(v => {
        const i = { };
        this.xCols.forEach(item => {
          i[item.prop] = v[item.prop];
        });
        return i;
      });
    },
    showData() {
      const { innerReversed, filterData, data } = this;
​
      let colLen = Infinity;
      let rowLen = 0;
      let showData = [];
​
      const originData = filterData.map((v) => {
        let obj = { ...v };
        delete obj[this.yKey.prop];
        let arr = Object.entries(obj);
        colLen = Math.min(colLen, arr.length);
        return arr;
      });
      rowLen = originData?.length;
​
      if(colLen == Infinity || !rowLen) return [];
      if(!innerReversed) {
        showData = data;
      }
      else {
        let initData = new Array(colLen)
        .fill(0)
        .map(() => new Array(rowLen).fill(0));
​
        for (let x = 0; x < rowLen; x++) {
          for (let y = 0; y < colLen; y++) {
            initData[y][x] = originData[x][y];
            initData[y][x][0] = `${this.yKey.prop}${x + 1}`;
          }
        }
​
        showData = initData.map((item, idx) => {
          let obj = Object.fromEntries(item);
          obj[this.xKey.prop] = this.xCols[idx].label;
          return obj;
        });
      }
​
      return showData;
    },
    tableHeight() {
      const { height, showData, maxHeight } = this;
      const allHeight = showData.length * 50 + 45;
      let th = height ? height : allHeight > maxHeight ? maxHeight : allHeight;
      return th;
    }
  },
  methods: {
    reverse() {
      this.innerReversed = !this.innerReversed;
    }
  }
};
</script>

使用:

<template>
    <div class="head">
        <span>测试</span>
        <el-button size="mini" @click="$refs['test'].reverse()">反转</el-button>
    </div>
    <div class="table-sp">
      <DoubleThTable
        ref="test"
        :xKey="{ prop: 'sys', label: '系统' }"
        :xCols="[                { prop: 'sys1', label: '系统1' },                 { prop: 'sys2', label: '系统2' },                 { prop: 'sys3', label: '系统3' }]"
        :yKey="{ prop: 'range', label: '范围' }"
        :yCols="['范围1','范围2','范围3', '范围4']"
        :data="[          { range: '范围1', sys1: '1-1', sys2: '1-2', sys3: '1-3'},          { range: '范围2', sys1: '2-1', sys2: '2-2', sys3: '2-3'},          { range: '范围3', sys1: '3-1', sys2: '3-2', sys3: '3-3'},          { range: '范围4', sys1: '4-1', sys2: '4-2', sys3: '4-3'}]"
        :height="296"
      >
      </DoubleThTable>
    </div>
</template>
​
<script>
import DoubleThTable from './DoubleThTable.vue';
    
export default {
  components: {  DoubleThTable },
};
</script>

个人博客,薛定谔的学习笔记