說明:
由於本文中使用的函數直接復制過來改了改,所有總歸會是差不多的,但是也只是更方便兩者進行對照來使得讀者更加容易明白一些細節上的問題。
在我們按照需求把相應的數據進行合並操作后,新的問題也隨之而來,那就是在單元格的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="width: 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樣式的類名。