由element-ui的table引发的系列问题---单元格合并hover样式

参考文章

说明:

由于本文中使用的函数直接复制过来改了改,所有总归会是差不多的,但是也只是更方便两者进行对照来使得读者更加容易明白一些细节上的问题。

在我们按照需求把相应的数据进行合并操作后,新的问题也随之而来,那就是在单元格的hover样式上依旧不是那么尽人意。

如下图所示,鼠标经过首行的时候,无法将具有合并的行进行全部高亮,而是之后被合并的行具有高亮显示

 再来看下官方示例,也是如此:

预期效果:

 

想要解决这个问题,直接借助官方提供的一个属性( row-class-name )和两个事件( cell-mouse-enter、cell-mouse-leave )

属性介绍如下图所示:

 

以下是一大坨的代码,请查收。

<template>
  <div>
    <el-table
      :data="tableData"
      :span-method="spanMethod"
      :row-class-name="tableRowClassName"
      border
      style=" 100%"
      @cell-mouse-enter="cellMouseEnter"
      @cell-mouse-leave="cellMouseLeave"
      >
      <el-table-column
        prop="id"
        label="ID"
        width="180">
      </el-table-column>
      <el-table-column
        prop="name"
        label="姓名">
      </el-table-column>
      <el-table-column
        prop="amount1"
        label="数值 1">
      </el-table-column>
      <el-table-column
        prop="amount2"
        label="数值 2">
      </el-table-column>
      <el-table-column
        prop="amount3"
        label="数值 3">
      </el-table-column>
    </el-table>
  </div>
</template>

<script>
export default {
  data () {
    return {
      tableData: [
        {
          id: '12987122',
          name: '王小虎',
          amount1: '234',
          amount2: '3.2',
          amount3: 10
        }, {
          id: '1298712',
          name: '王小虎',
          amount1: '165',
          amount2: '4.43',
          amount3: 12
        }, {
          id: '12987124',
          name: '王小二',
          amount1: '324',
          amount2: '1.9',
          amount3: 9
        }, {
          id: '12987125',
          name: '张三',
          amount1: '621',
          amount2: '2.2',
          amount3: 17
        }, {
          id: '12987125',
          name: '张三',
          amount1: '539',
          amount2: '4.1',
          amount3: 15
        }
      ],
      spanArr: [],
      position: 0,
      needSpan: ['id', 'name'], // 需要合并的属性
      spanArrObj: {
        id: [],
        name: []
      },
      rowIndex: '-1',
      OrderIndexArr: [],
      hoverOrderArr: []
    }
  },
  created () {
    this.getSpanArr()
  },
  watch: {
    tableData () {
      this.getOrderNumber()
    }
  },
  mounted () {
    this.getOrderNumber()
  },
  methods: {
    // 合并行方法
    spanMethod ({ row, column, rowIndex, columnIndex }) {
      if (columnIndex === 0) {
        const _row = this.spanArrObj['id'][rowIndex]
        const _col = _row > 0 ? 1 : 0
        return {
          rowspan: _row,
          colspan: _col
        }
      }
      if (columnIndex === 1) {
        const _row = this.spanArrObj['name'][rowIndex]
        const _col = _row > 0 ? 1 : 0
        return {
          rowspan: _row,
          colspan: _col
        }
      }
    },
    // 获取合并行参数(数组)
    rowspan (prop, first = 'id') {
      // this.position = 0
      // this.spanArrObj = []
      this.tableData.forEach((item, index) => {
        if (index === 0) {
          this.spanArrObj[prop].push(1)
          this.position = 0
        } else {
          if (this.tableData[index][first] === this.tableData[index - 1][first] && this.tableData[index][prop] === this.tableData[index - 1][prop]) {
            this.spanArrObj[prop][this.position] += 1
            this.spanArrObj[prop].push(0)
          } else {
            this.spanArrObj[prop].push(1)
            this.position = index
          }
        }
      })
    },
    getSpanArr () {
      this.needSpan.forEach(item => {
        this.rowspan(item)
      })
    },
    // editRow () {
    //   this.$forceUpdate() // vue提供的方法 - 强制刷新视图
    // },
    tableRowClassName ({ row, rowIndex }) {
      var arr = this.hoverOrderArr
      for (var i = 0; i < arr.length; i++) {
        if (rowIndex === arr[i]) {
          return 'success-row'
        }
      }
    },

    cellMouseEnter (row, column, cell, event) {
      this.rowIndex = row.rowIndex
      this.hoverOrderArr = []
      this.OrderIndexArr.forEach((element) => {
        if (element.indexOf(this.rowIndex) >= 0) {
          this.hoverOrderArr = element
        }
      })
    },

    cellMouseLeave (row, column, cell, event) {
      this.rowIndex = '-1'
      this.hoverOrderArr = []
    },

    // 获取相同编号的数组
    getOrderNumber () {
      var OrderObj = {}
      this.tableData.forEach((element, index) => {
        element.rowIndex = index
        if (OrderObj[element.id]) {
          OrderObj[element.id].push(index)
        } else {
          OrderObj[element.id] = []
          OrderObj[element.id].push(index)
        }
      })

      for (var k in OrderObj) {
        if (OrderObj[k].length > 1) {
          this.OrderIndexArr.push(OrderObj[k])
        }
      }
    }
  }
}
</script>

<style lang="less" scoped>
  /deep/.el-table .success-row {
    background: #f5f7fa;
  }
</style>

由于太懒了,具体细节就不多说了,就大概总结一下:

①在拿到这个表格的数据(tableData)的时候,根据合并项的参照数据(id)进行去重,然后塞入一个rowIndex作为判断

当前鼠标hover的行是否与其它行存在合并关系,getOrderNumber做的就是这个工作,因为这里的数据是写死的,所以

我在mounted中多调用了一次这个方法,实际开发中,则只需要监听tableData的变化来生成判断依据rowIndex即可。

②通过上述方法塞入判断依据后再通过鼠标的移入移出table事件来进行交互(判断当前hover中的行是否与其它行存在合并关系,并将有关系的这几行放在hoverOrderArr这个数组里),也就是这俩事件( cell-mouse-enter、cell-mouse-leave )

③最后再通过( row-class-name )这个属性所对应的函去遍历第二步中得到的数组,以确定是否要给某行加上hover样式的类名。

原文地址:https://www.cnblogs.com/ViavaCos/p/12855864.html