vue+element实现多级表头加树结构

标题两种展示方式

方式一

完整代码:

javascript 复制代码
<template>
  <div class="box">
    <el-table
      ref="areaPointTable"
      :data="tableData"
      border
      :span-method="objectSpanMethod"
      :header-cell-style="tableHeaderMerge"
    >
      <el-table-column
        :prop="item.prop?item.prop:''"
        :label="item.titleName"
        align="center"
        v-for="(item, index) in tableHeader"
        :key="index"
      >
        <template slot-scope="{ row, column, $index }">
          <span
            v-if="column.property=='bigType'"
            @click="handleDeleteN(row, column, $index)"
            :class="row[item.prop] == '未达标' ? 'text-red' : ''"
            :style="row[item.prop] < 0 ? 'color:red;' : ''"
            style="cursor: pointer;"
          >
            {{
            isNaN(row[item.prop])?row[item.prop]:
            row[item.prop] >= 0
            ? row[item.prop]
            : Math.abs(row[item.prop])
            }}
          </span>
          <span
            v-else
            :class="row[item.prop] == '未达标' ? 'text-red' : ''"
            :style="row[item.prop] < 0 ? 'color:red;' : ''"
          >
            {{
            isNaN(row[item.prop])?row[item.prop]:
            row[item.prop] >= 0
            ? row[item.prop]
            : Math.abs(row[item.prop])
            }}
          </span>
        </template>
        <el-table-column
          :prop="iteam.prop"
          :label="iteam.titleName"
          align="center"
          v-for="(iteam, idx) in item.childTitle"
          :key="idx"
        >
          <template slot-scope="{ row }">
            <span
              :class="row[iteam.prop] == '未达标' ? 'text-red' : ''"
              :style="row[iteam.prop] < 0 ? 'color:red;' : ''"
            >
              {{
              isNaN(row[iteam.prop])?row[iteam.prop]:
              row[iteam.prop] >= 0
              ? row[iteam.prop]
              : Math.abs(row[iteam.prop])
              }}
            </span>
          </template>
        </el-table-column>
      </el-table-column>
    
    </el-table>
  </div>
</template>
<script>
export default {
  name: 'demo',
  data() {
    return {
      input: '',
    
      tableHeader: [
        {
          titleName: '类型',
          childTitle: null,
          prop: 'bigType',
        },
        {
          titleName: '类型',
          childTitle: null,
          prop: 'smallType1',
        },
        {
          titleName: 'A',
          childTitle: [
            {
              titleName: 'a1',
              childTitle: null,
              prop: 'prop2',
            },
            {
              titleName: 'a2',
              childTitle: null,
              prop: 'prop3',
            },
          ],
        },
        {
          titleName: 'B',
          childTitle: [
            {
              titleName: 'b1',
              childTitle: null,
              prop: 'prop4',
            },
            {
              titleName: 'b2',
              childTitle: null,
              prop: 'prop5',
            },
            {
              titleName: 'b3',
              childTitle: null,
              prop: 'prop6',
            },
            {
              titleName: 'b4',
              childTitle: null,
              prop: 'prop7',
            },
          ],
        },
        {
          titleName: 'C',
          childTitle: [
            {
              titleName: 'c1',
              childTitle: null,
              prop: 'prop8',
            },
            {
              titleName: 'c2',
              childTitle: null,
              prop: 'prop9',
            },
            {
              titleName: 'c3',
              childTitle: null,
              prop: 'prop10',
            },
          ],
        },
        {
          titleName: 'D',
          childTitle: [
            {
              titleName: 'd1',
              childTitle: null,
              prop: 'prop11',
            },
            {
              titleName: 'd2',
              childTitle: null,
              prop: 'prop12',
            },
          ],
        },
        {
          titleName: 'W',
          childTitle: [
            {
              titleName: 'w1',
              childTitle: null,
              prop: 'prop13',
            },
            {
              titleName: 'w2',
              childTitle: null,
              prop: 'prop14',
            },
          ],
        },
      ],
      initTableData: [
        {
          id: 23,
          bigType: 'AA',
          smallType1: 'aa1',
          prop2: '1.0',
          prop3: '2.5',
          prop4: '40.0',
          prop5: '1.0',
          prop6: '2.5',
          prop7: '未达标',
          prop8: '0.0',
          prop9: '0.0',
          prop10: '0.0',
          prop11: '1.0',
          prop12: '100.0',
          prop13: '1.0',
          prop14: '100.0',
          rowspan: 1,
        },
        {
          id: 38,
          bigType: 'AA',
          smallType1: 'aa2',
          prop2: '8.0',
          prop3: '100.0',
          prop4: '2.0',
          prop5: '8.0',
          prop6: '100.0',
          prop7: '达标',
          prop8: '8.0',
          prop9: '0.0',
          prop10: '0.0',
          prop11: '6.0',
          prop12: '75.0',
          prop13: '8.0',
          prop14: '100.0',
        },
        {
          id: 53,
          bigType: 'AA',
          smallType1: 'aa3',
          prop2: '19.0',
          prop3: '47.5',
          prop4: '40.0',
          prop5: '19.0',
          prop6: '47.5',
          prop7: '未达标',
          prop8: '19.0',
          prop9: '0.0',
          prop10: '0.0',
          prop11: '19.0',
          prop12: '100.0',
          prop13: '19.0',
          prop14: '100.0',
        },
        {
          id: 68,
          bigType: 'AA',
          smallType1: 'aa4',
          prop2: '0.0',
          prop3: '0.0',
          prop4: '0.0',
          prop5: '0.0',
          prop6: '0.0',
          prop7: '未达标',
          prop8: '0.0',
          prop9: '0.0',
          prop10: '0.0',
          prop11: '0.0',
          prop12: '0.0',
          prop13: '0.0',
          prop14: '0.0',
        },
        {
          id: 83,
          bigType: 'XX',
          smallType1: 'xx1',
          prop2: '55.0',
          prop3: '0.0',
          prop4: '0.0',
          prop5: '76.0',
          prop6: '0.0',
          prop7: '未达标',
          prop8: '64.0',
          prop9: '0.0',
          prop10: '0.0',
          prop11: '65.0',
          prop12: '85.53',
          prop13: '61.0',
          prop14: '80.26',
          rowspan: 1,
        },
        {
          id: 831,
          bigType: 'XX',
          smallType1: 'xx2',
          prop2: '55.0',
          prop3: '0.0',
          prop4: '0.0',
          prop5: '76.0',
          prop6: '0.0',
          prop7: '未达标',
          prop8: '64.0',
          prop9: '0.0',
          prop10: '0.0',
          prop11: '65.0',
          prop12: '85.53',
          prop13: '61.0',
          prop14: '80.26',
          rowspan: 1,
        },
        {
          id: 832,
          bigType: 'XX',
          smallType1: 'xx3',
          prop2: '55.0',
          prop3: '0.0',
          prop4: '0.0',
          prop5: '76.0',
          prop6: '0.0',
          prop7: '未达标',
          prop8: '64.0',
          prop9: '0.0',
          prop10: '0.0',
          prop11: '65.0',
          prop12: '85.53',
          prop13: '61.0',
          prop14: '80.26',
          rowspan: 1,
        },
        {
          id: 98,
          bigType: 'QQ',
          smallType1: '-',
          prop2: '0.0',
          prop3: '0.0',
          prop4: '0.0',
          prop5: '0.0',
          prop6: '0.0',
          prop7: '未达标',
          prop8: '0.0',
          prop9: '0.0',
          prop10: '0.0',
          prop11: '0.0',
          prop12: '0.0',
          prop13: '0.0',
          prop14: '0.0',
          rowspan: 1,
        },
        {
          id: 113,
          bigType: 'WW',
          smallType1: 'ww',
          prop2: '0.0',
          prop3: '0.0',
          prop4: '0.0',
          prop5: '0.0',
          prop6: '0.0',
          prop7: '未达标',
          prop8: '0.0',
          prop9: '0.0',
          prop10: '0.0',
          prop11: '0.0',
          prop12: '0.0',
          prop13: '0.0',
          prop14: '0.0',
          rowspan: 1,
        },
        {
          id: 128,
          bigType: 'DD',
          smallType1: 'dd1',
          prop2: '1.0',
          prop3: '1.25',
          prop4: '80.0',
          prop5: '1.0',
          prop6: '1.25',
          prop7: '未达标',
          prop8: '1.0',
          prop9: '0.0',
          prop10: '0.0',
          prop11: '1.0',
          prop12: '100.0',
          prop13: '1.0',
          prop14: '100.0',
          rowspan: 1,
        },
        {
          id: 1281,
          bigType: 'DD',
          smallType1: 'dd2',
          prop2: '1.0',
          prop3: '1.25',
          prop4: '80.0',
          prop5: '1.0',
          prop6: '1.25',
          prop7: '未达标',
          prop8: '1.0',
          prop9: '0.0',
          prop10: '0.0',
          prop11: '1.0',
          prop12: '100.0',
          prop13: '1.0',
          prop14: '100.0',
          rowspan: 1,
        },
        {
          id: 1282,
          bigType: 'DD',
          smallType1: 'dd3',
          prop2: '1.0',
          prop3: '1.25',
          prop4: '80.0',
          prop5: '1.0',
          prop6: '1.25',
          prop7: '未达标',
          prop8: '1.0',
          prop9: '0.0',
          prop10: '0.0',
          prop11: '1.0',
          prop12: '100.0',
          prop13: '1.0',
          prop14: '100.0',
          rowspan: 1,
        },
      ],
      dialogTypeMergeArr: [
        {
          rowspan: 4,
          colspan: 1,
        },
        {
          rowspan: 0,
          colspan: 0,
        },
        {
          rowspan: 0,
          colspan: 0,
        },
        {
          rowspan: 0,
          colspan: 0,
        },
        {
          rowspan: 1,
          colspan: 1,
        },
        {
          rowspan: 1,
          colspan: 1,
        },
        {
          rowspan: 1,
          colspan: 1,
        },
        {
          rowspan: 1,
          colspan: 1,
        },
      ],
      tableData: [],
      select_box: [],
    }
  },
  mounted() {
    this.dealTableData(this.initTableData)
    this.dialogHeaderMergeArr = this.mergeTableHeader(this.tableHeader)
  },
  methods: {
    tableHeaderMerge({ row, column, rowIndex, columnIndex }) {
      console.log(312312)
      if (rowIndex == 0) {
        this.$nextTick(() => {
          // row[columnIndex].colSpan=this.dialogHeaderMergeArr[columnIndex];
          if (document.getElementsByClassName(column.id).length !== 0) {
            document
              .getElementsByClassName(column.id)[0]
              .setAttribute('colSpan', this.dialogHeaderMergeArr[columnIndex])
          }
        })
        if (this.dialogHeaderMergeArr[columnIndex] == 0) {
          return { display: 'none' }
        }
      }
    },
    mergeTableHeader(data) {
      let countArr = []
      let labelArr = []
      data.map((item) => {
        labelArr = countArr.map((obj) => obj.label)
        if (item.childTitle) {
          countArr.push({
            label: item.titleName,
            colSpan: item.childTitle.length,
            hasChild: true,
          })
        } else {
          if (labelArr.includes(item.titleName)) {
            countArr.map((iteam) => {
              if (iteam.label == item.titleName) iteam.colSpan += 1
            })
          } else {
            countArr.push({
              label: item.titleName,
              colSpan: 1,
              hasChild: false,
            })
          }
        }
      })
      let tableHeaderCountArr = []
      countArr.map((item) => {
        if (!item.hasChild) {
          for (var i = 0; i < item.colSpan - 1; i++) {
            tableHeaderCountArr.push(0)
          }
        }
        tableHeaderCountArr.push(item.colSpan)
      })
      return tableHeaderCountArr
    },
    /**
     * 处理表格数据合并行
     */
    dealTableData(data) {
      //把日期相同的数据并排在一块
      const list = this.margePropData(data, 'bigType')
      //处理日期相同的合并
      this.tableData = this.mergeRows(list, 'bigType')
    },

    handleDeleteN(row, column, $index) {
      this.initTableData.filter((item, index) => {
        if (row.bigType === item.bigType && index !== $index) {
        }

        // row.bigType === item.bigType && index !== 0
      })
      let curChildern = this.tableData.filter(
        (item, index) => row.bigType === item.bigType && index !== $index
      )
      let curChildern_init = this.initTableData.filter(
        (item, index) => row.bigType === item.bigType && row.smallType1 !== item.smallType1
      )

      if (this.tableData.filter((item, index) => row.bigType === item.bigType).length == 1) {
        if (curChildern.length > 1) {
          this.tableData.push(...curChildern)

          this.dealTableData(this.tableData)
        } else {
          this.tableData.push(...curChildern_init)

          this.dealTableData(this.tableData)
          return
        }
      } else {
        let newTableData = this.tableData.filter(
          (e) => curChildern.filter((x) => e.id != x.id).length == curChildern.length
        )

        // this.tableData = newTableData
        // this.tableData = this.tableData.filter((it, i) => row.id === it.id)
        this.dealTableData(newTableData)
      }
    },

    /**
     * 合并行
     * @param row
     * @param column
     * @param rowIndex
     * @param columnIndex
     * @returns {{colspan: number, rowspan: (number|*)}}
     */
    objectSpanMethod({ row, column, rowIndex, columnIndex }) {
      if ([0].includes(columnIndex)) {
        return {
          rowspan: row.rowspan,
          colspan: 1,
        }
      }
      // if (column.property == 'bigType') {
      //   return this.dialogTypeMergeArr[rowIndex]
      // }
    },
    /**
     * 数组中,某个属性相同的数据放在一块,如把某个日期相同的相连一起
     * @param list 传入的数组
     * @param prop 那个属性相同的数据
     * @returns {*[]}
     */
    margePropData(list = [], prop) {
      let arr = [],
        tempArr = {}
      list.forEach((item) => {
        if (!tempArr[item[prop]]) {
          tempArr[item[prop]] = [item]
        } else {
          tempArr[item[prop]].push(item)
        }
      })
      for (const tempArrKey in tempArr) {
        arr = [...arr, ...tempArr[tempArrKey]]
      }
      return arr
    },
    /**
     * 根据当前数据的位置,在数组中插入数据
     * 如数组【1,2,4,5】想要在2后面插入3,
     *1:首先获取到2的下标,
     *2:然后获取要插入之前的数据,获取要插入之后的数据,中间就是插入的位置
     *3:最后把这三个按顺序合并就得到在想要的位置插入数据
     * @param list
     * @param index
     * @param target
     */
    insertArrPositionOfIndex(list = [], index = 0, target = {}) {
      //根据index 找出小于index的数据放在左边
      const leftList = list.filter((t, i) => i < index)
      //根据index 找出大于index的数据放在右边
      const rightList = list.filter((t, i) => i >= index)
      // 最终合并数据
      return [...leftList, target, ...rightList]
    },
    /**
     * 合并行
     * @param list
     * @param prop
     */
    mergeRows(list = [], prop) {
      list.forEach((ele) => {
        ele.rowspan = 1
      })
      const len = list.length
      for (let i = 0; i < len; i++) {
        for (let j = i + 1; j < len; j++) {
          if (list[i][prop] === list[j][prop]) {
            list[i].rowspan++
            list[j].rowspan--
          }
        }
        // 这里跳过已经重复的数据
        i = i + list[i].rowspan - 1
      }
      return list
    },
  },
  /**
   * 对象数组去重
   * @param arr 数组
   * @param prop 根据什么字段去重
   * @returns {any[]}
   */ arrayDeduplication(arr, prop) {
    let map = new Map()
    return arr.filter((item) => !map.has(item[prop]) && map.set(item[prop], 1))
  },
}
</script>

方式二

javascript 复制代码
<template>
  <el-table
    :data="tableData"
    row-key="id"
    :tree-props="{children: 'children', hasChildren: 'hasChildren'}"
  >
    <el-table-column
      v-for="(column, index) in columns"
      :key="index"
      :label="column.titleName"
      :prop="column.prop"
      :width="column.width"
      :align="column.align"
    >
      <template slot-scope="{ row, $index }">{{ row[column.prop] }}</template>
      <el-table-column
        v-if="column.childTitle"
        v-for="(subColumn, subIndex) in column.childTitle"
        :key="subIndex"
        :label="subColumn.titleName"
        :prop="subColumn.prop"
        :width="subColumn.width"
        :align="subColumn.align"
      >
        <template slot-scope="{ row, $index }">{{ row[subColumn.prop] }}</template>
      </el-table-column>
    </el-table-column>
  </el-table>
</template>

<script>
export default {
  data() {
    return {
      tableData: [
        {
          id: 1,
          bigType: 'AA',
          smallType1: 'aa1',
          prop2: '2.0',
          prop3: '5.0',
          prop4: '40.0',
          prop5: '2.0',
          prop6: '5.0',
          prop7: '未达标',
          prop8: '0.0',
          prop9: '0.0',
          prop10: '0.0',
          prop11: '2.0',
          prop12: '100.0',
          prop13: '2.0',
          prop14: '100.0',
          children: [
            {
              bigType: 'aa1',
              smallType1: 'aa1',
              prop2: '2.0',
              prop3: '5.0',
              prop4: '40.0',
              prop5: '2.0',
              prop6: '5.0',
              prop7: '未达标',
              prop8: '0.0',
              prop9: '0.0',
              prop10: '0.0',
              prop11: '2.0',
              prop12: '100.0',
              prop13: '2.0',
              prop14: '100.0',
              id: 2,
            },
            {
              bigType: 'aa2',
              smallType1: 'aa2',
              prop2: '8.0',
              prop3: '100.0',
              prop4: '2.0',
              prop5: '8.0',
              prop6: '100.0',
              prop7: '达标',
              prop8: '8.0',
              prop9: '0.0',
              prop10: '0.0',
              prop11: '6.0',
              prop12: '75.0',
              prop13: '8.0',
              prop14: '100.0',
              id: 3,
            },
            {
              bigType: 'aa3',
              smallType1: 'aa3',
              prop2: '19.0',
              prop3: '47.5',
              prop4: '40.0',
              prop5: '19.0',
              prop6: '47.5',
              prop7: '未达标',
              prop8: '19.0',
              prop9: '0.0',
              prop10: '0.0',
              prop11: '19.0',
              prop12: '100.0',
              prop13: '19.0',
              prop14: '100.0',
              id: 4,
            },
            {
              bigType: 'aa4',
              smallType1: 'aa4',
              prop2: '0.0',
              prop3: '0.0',
              prop4: '0.0',
              prop5: '0.0',
              prop6: '0.0',
              prop7: '未达标',
              prop8: '0.0',
              prop9: '0.0',
              prop10: '0.0',
              prop11: '0.0',
              prop12: '0.0',
              prop13: '0.0',
              prop14: '0.0',
              id: 5,
            },
          ],
        },
        {
          id: 6,
          bigType: 'BB',
          prop2: '55.0',
          prop3: '0.0',
          prop4: '0.0',
          prop5: '76.0',
          prop6: '0.0',
          prop7: '未达标',
          prop8: '64.0',
          prop9: '0.0',
          prop10: '0.0',
          prop11: '65.0',
          prop12: '85.53',
          prop13: '61.0',
          prop14: '80.26',
          children: [
            {
              bigType: 'bb1',
              smallType1: 'bb1',
              prop2: '55.0',
              prop3: '0.0',
              prop4: '0.0',
              prop5: '76.0',
              prop6: '0.0',
              prop7: '未达标',
              prop8: '64.0',
              prop9: '0.0',
              prop10: '0.0',
              prop11: '65.0',
              prop12: '85.53',
              prop13: '61.0',
              prop14: '80.26',
              id: 7,
            },
            {
              bigType: 'bb2',
              smallType1: 'bb2',
              prop2: '55.0',
              prop3: '0.0',
              prop4: '0.0',
              prop5: '76.0',
              prop6: '0.0',
              prop7: '未达标',
              prop8: '64.0',
              prop9: '0.0',
              prop10: '0.0',
              prop11: '65.0',
              prop12: '85.53',
              prop13: '61.0',
              prop14: '80.26',
              id: 17,
            },
          ],
        },
        {
          id: 8,
          bigType: 'DD',
          prop2: '0.0',
          prop3: '0.0',
          prop4: '0.0',
          prop5: '0.0',
          prop6: '0.0',
          prop7: '未达标',
          prop8: '0.0',
          prop9: '0.0',
          prop10: '0.0',
          prop11: '0.0',
          prop12: '0.0',
          prop13: '0.0',
          prop14: '0.0',
          children: [
            {
              bigType: 'dd1',
              smallType1: 'dd1',
              prop2: '0.0',
              prop3: '0.0',
              prop4: '0.0',
              prop5: '0.0',
              prop6: '0.0',
              prop7: '未达标',
              prop8: '0.0',
              prop9: '0.0',
              prop10: '0.0',
              prop11: '0.0',
              prop12: '0.0',
              prop13: '0.0',
              prop14: '0.0',
              id: 9,
            },
          ],
        },
      ],
      columns: [
        {
          titleName: '类型',
          childTitle: null,
          prop: 'bigType',
        },

        {
          titleName: 'A',
          childTitle: [
            {
              titleName: 'a1',
              childTitle: null,
              prop: 'prop2',
            },
            {
              titleName: 'a2',
              childTitle: null,
              prop: 'prop3',
            },
          ],
        },
        {
          titleName: 'B',
          childTitle: [
            {
              titleName: 'b1',
              childTitle: null,
              prop: 'prop4',
            },
            {
              titleName: 'b2',
              childTitle: null,
              prop: 'prop5',
            },
            {
              titleName: 'b3',
              childTitle: null,
              prop: 'prop6',
            },
            {
              titleName: 'b4',
              childTitle: null,
              prop: 'prop7',
            },
          ],
        },
        {
          titleName: 'C',
          childTitle: [
            {
              titleName: 'c1',
              childTitle: null,
              prop: 'prop8',
            },
            {
              titleName: 'c2',
              childTitle: null,
              prop: 'prop9',
            },
            {
              titleName: 'c3',
              childTitle: null,
              prop: 'prop10',
            },
          ],
        },
        {
          titleName: 'D',
          childTitle: [
            {
              titleName: 'd1',
              childTitle: null,
              prop: 'prop11',
            },
            {
              titleName: 'd2',
              childTitle: null,
              prop: 'prop12',
            },
          ],
        },
        {
          titleName: 'W',
          childTitle: [
            {
              titleName: 'w1',
              childTitle: null,
              prop: 'prop13',
            },
            {
              titleName: 'w2',
              childTitle: null,
              prop: 'prop14',
            },
          ],
        },
      ],
    }
  },
}
</script>
相关推荐
GIS程序媛—椰子44 分钟前
【Vue 全家桶】7、Vue UI组件库(更新中)
前端·vue.js
DogEgg_0011 小时前
前端八股文(一)HTML 持续更新中。。。
前端·html
ZL不懂前端1 小时前
Content Security Policy (CSP)
前端·javascript·面试
木舟10091 小时前
ffmpeg重复回听音频流,时长叠加问题
前端
王大锤43911 小时前
golang通用后台管理系统07(后台与若依前端对接)
开发语言·前端·golang
我血条子呢2 小时前
[Vue]防止路由重复跳转
前端·javascript·vue.js
黎金安2 小时前
前端第二次作业
前端·css·css3
啦啦右一2 小时前
前端 | MYTED单篇TED词汇学习功能优化
前端·学习
半开半落2 小时前
nuxt3安装pinia报错500[vite-node] [ERR_LOAD_URL]问题解决
前端·javascript·vue.js·nuxt