el-table合计行单元格合并、单元格样式修改

该文章介绍了如何在ElementUI的el-table组件中自定义合计行,包括将其移动到头部、改变字体颜色和背景色、计算平均值和总数、调整单元格样式,并处理固定列时的显示问题。通过CSS和JavaScript方法实现了合计行的样式修改和功能增强。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、目标效果

        源码放在下面,复制粘贴即可

        (1)合计行放在头部,且字体颜色变粗、合计行背景色变粗

        (2)合计行年龄算平均值且字体颜色为绿色,财产算总数且字体颜色为红色 

2、原理

2.1、el-table中show-summary 合计行默认放在尾部

        加上如下css即可:父选择器  /deep/ 子选择器实现样式穿透

/* 合计行位置修改开始 */
.el-table {
    display: flex;
    flex-direction: column;
}

.el-table /deep/ .el-table__body-wrapper {
    order: 1;
}

/* 合计行位置修改结束*/

2.2、合计行整体样式修改

/* 合计行整体样式修改开始 */
.el-table /deep/ .el-table__footer-wrapper tbody td {
    background: black;
    color: white;
    font-weight: bolder;
}

/* 合计行整体样式修改结束*/

2.3、合计方法::summary-method="getSummaries"

 // 合计行方法
        getSummaries(param) {
            const { columns, data } = param;
            const sums = [];
            columns.forEach((column, index) => {
                if (column.property == 'date') {
                    sums[index] = '总价';
                    return;
                }

                // values是每一列的数据是一个数组
                const values = data.map(item => Number(item[column.property]));
                
                // 数字列才进行合计计算
                if (!values.every(value => isNaN(value))) {
                    // 对values进行一个累加操作,累加那些非NAN的值
                    const total = values.reduce((prev, curr) => {
                        const value = Number(curr);
                        if (!isNaN(value)) {
                            return prev + curr;
                        } else {
                            return prev;
                        }
                    }, 0);

                    // 年龄计算平均值
                    if (column.property == 'age') {
                        sums[index] = total / data.length
                    }

                    // 财产计算总数
                    if (column.property == 'money') {
                        sums[index] = total}
                    }

                }
            });

            // 将合计结果返回,是一个数组,每个位置的值与表格的列一一对应
            return sums
        }

        columns展示每一列的信息,是一个对象数组

        data为每一行的信息,也是一个对象数组,不算上合计行哦!

        sums为合计行,在typescript中是一个元祖,即数组里面可以存放不同类型的元素

  

2.4、合计行单元格样式

        2.4.1、css方式

.el-table /deep/ .el-table__footer-wrapper tbody td:nth-child(3) {
    color: lightgreen;
    font-weight: bolder;
}

.el-table /deep/ .el-table__footer-wrapper tbody td:nth-child(4) {
    color: red;
    font-weight: bolder;
}

        缺点:需要手动计算每列的位置,一旦列的位置发生变化,不好维护

        2.4.2、jsx方式

        合计行中返回jsx,生成一个VNode,动态生成样式

 // 年龄计算平均值(绿色)
                    if (column.property == 'age') {
                        sums[index] = <span class={'green'}>{total / data.length}</span>
                    }

                    // 财产计算总数(红色)
                    if (column.property == 'money') {
                        sums[index] = <span class={'red'}>{total}</span>
                    }
.red {
    color: red;
    font-weight: bolder;
}

.green {
    color: lightgreen;
    font-weight: bolder;
}

        

        sums返回VNode

         

2.5、合计行单元格合并

        2.5.1、别人博客的方式(会报错)        

 watch: {
        表格数据: {
            immediate: true,
            handler() {
                    const tds = document.querySelectorAll('#table .el-table__footer-wrapper tr>td');
                    tds[0].colSpan = 2;
                    tds[0].style.textAlign = 'center'
                    tds[1].style.display = 'none'
            }
        }
    },

        2.5.2、elementUI中合并行的方法

        :span-method是不包括合计行的

        2.5.3、本篇文章的方法 (推荐

                在方法一的基础上改造:

 watch: {
        tableData: {
            immediate: true,
            handler() {
                setTimeout(() => {
                    const tds = document.querySelectorAll('#table .el-table__footer-wrapper tr>td');
                    tds[0].colSpan = 2;
                    tds[0].style.textAlign = 'center'
                    tds[1].style.display = 'none'
                }, 0)
            }
        }
    },

                为什么这样却可以?              

        Vue 推荐使用 template 来创建 HTML。但不是真实的DOM节点。vue会先利用对象中的render 函数,生成虚拟DOM节点并挂载挂载的真实DOM是进行异步渲染的并且在修改完状态后也是异步的方式进行渲染。代码中将document.querySelectorAll操作定义为同步任务,此时事件队列应该是:

        同步队列:获取dom元素
        异步队列:从虚拟节点转真实节点并进行渲染
        根据先同步后异步的执行流程,是无法合并单元格的

        使用setTimeout 可以将元素放在异步队列执行,等页面加载完毕之后在获取dom元素就可以成功了!

 

2.6、合计行存在固定列

        合计行存在固定列时,会出现如下问题:

        (1)固定列中的合计行跑到底部了

        (2)合并单元格效果消失

 

 

        加上如下css以及修改部分js

/* 存在固定列时,合计行位置修改开始 */
.el-table /deep/ .el-table__fixed {
    display: flex;
    flex-direction: column;
}

.el-table /deep/ .el-table__fixed-footer-wrapper,
.el-table /deep/ .el-table__fixed-body-wrapper,
.el-table /deep/ .el-table__fixed-header-wrapper {
    position: initial;
}

.el-table /deep/ .el-table__fixed-body-wrapper {
    order: 1;
}

.el-table /deep/ .el-table__fixed-footer-wrapper tbody td.el-table__cell {
    border-top: none;
    background: black;
    color: white;
    font-weight: bolder;

}

/* 存在固定列时,合计行位置修改开始 */

    

 

        最终效果如下:

3、源码

        App.vue

<template>
  <div id="app">
    <SummaryTable></SummaryTable>
  </div>
</template>
 
<script>
import SummaryTable from '@/components/SummaryTable'
export default {
  components: {
    SummaryTable
  },
  name: 'App',
  data() {
    return {

    }
  },
}
</script>
 
<style>
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
</style>

        SummaryTable.vue

<template>
    <div>
        <el-table ref="table" id="table" :data="tableData" border style="width: 100%" show-summary
            :summary-method="getSummaries">
            <el-table-column prop="date" label="日期" width="180" fixed="left">
            </el-table-column>
            <el-table-column prop="name" label="姓名" width="180" fixed="left">
            </el-table-column>
            <el-table-column prop="age" label="年龄"></el-table-column>
            <el-table-column prop="age" label="年龄"></el-table-column>
            <el-table-column prop="age" label="年龄"></el-table-column>
            <el-table-column prop="age" label="年龄"></el-table-column>
            <el-table-column prop="age" label="年龄"></el-table-column>
            <el-table-column prop="age" label="年龄"></el-table-column>
            <el-table-column prop="age" label="年龄"></el-table-column>
            <el-table-column prop="age" label="年龄"></el-table-column>
            <el-table-column prop="age" label="年龄"></el-table-column>
            <el-table-column prop="age" label="年龄"></el-table-column>
            <el-table-column prop="age" label="年龄"></el-table-column>
            <el-table-column prop="money" label="财产"></el-table-column>
            <el-table-column prop="money" label="财产"></el-table-column>
            <el-table-column prop="money" label="财产"></el-table-column>
            <el-table-column prop="money" label="财产"></el-table-column>
        </el-table>
    </div>
</template>
   
<script>

export default {
    name: 'App',
    data() {
        return {
            tableData: [{
                date: '2016-05-01',
                name: '王小虎',
                age: 13,
                money: 100
            }, {
                date: '2016-05-02',
                name: '王小虎',
                age: 25,
                money: 333
            }, {
                date: '2016-05-03',
                name: '王小虎',
                age: 33,
                money: 555
            }, {
                date: '2016-05-04',
                name: '王小虎',
                age: 23,
                money: 200
            },
            {
                date: '2016-05-05',
                name: '王小虎',
                age: 26,
                money: 666
            }],
        }
    },
    watch: {
        tableData: {
            immediate: true,
            handler() {
                setTimeout(() => {
                    const tds = document.querySelectorAll('#table .el-table__fixed-footer-wrapper tr>td');
                    tds[0].colSpan = 2;
                    tds[0].style.textAlign = 'center'
                    tds[1].style.display = 'none'
                }, 0)
            }
        }
    },
    methods: {
        // 合计行方法
        getSummaries(param) {
            const { columns, data } = param;
            const sums = [];
            columns.forEach((column, index) => {
                if (column.property == 'date') {
                    sums[index] = '总价';
                    return;
                }

                // values是每一列的数据是一个数组
                const values = data.map(item => Number(item[column.property]));
                if (!values.every(value => isNaN(value))) {
                    // 对values进行一个累加操作,累加那些非NAN的值
                    const total = values.reduce((prev, curr) => {
                        const value = Number(curr);
                        if (!isNaN(value)) {
                            return prev + curr;
                        } else {
                            return prev;
                        }
                    }, 0);

                    // 年龄计算平均值(绿色)
                    if (column.property == 'age') {
                        sums[index] = <span class={'green'}>{total / data.length}</span>
                    }

                    // 财产计算总数(红色)
                    if (column.property == 'money') {
                        sums[index] = <span class={'red'}>{total}</span>
                    }

                }
            });
            // 将合计结果返回,是一个数组,每个位置的值与表格的列一一对应
            return sums
        }
    }
}
</script>
   
<style scoped>
.red {
    color: red;
    font-weight: bolder;
}

.green {
    color: lightgreen;
    font-weight: bolder;
}

/* 存在固定列时,合计行位置修改开始 */
.el-table /deep/ .el-table__fixed {
    display: flex;
    flex-direction: column;
}

.el-table /deep/ .el-table__fixed-footer-wrapper,
.el-table /deep/ .el-table__fixed-body-wrapper,
.el-table /deep/ .el-table__fixed-header-wrapper {
    position: initial;
}

.el-table /deep/ .el-table__fixed-body-wrapper {
    order: 1;
}

.el-table /deep/ .el-table__fixed-footer-wrapper tbody td.el-table__cell {
    border-top: none;
    background: black;
    color: white;
    font-weight: bolder;
}

/* 存在固定列时,合计行位置修改开始 */

/* 默认有1px去掉样式影响 */
.el-table /deep/ .el-table__fixed::before {
    height: 0;
}

/* 合计行整体样式修改开始 */
.el-table /deep/ .el-table__footer-wrapper tbody td {
    background: black;
    color: white;
    font-weight: bolder;
}

/* 合计行整体样式修改结束*/


/* 合计行位置修改开始 */
.el-table {
    display: flex;
    flex-direction: column;
}

.el-table /deep/ .el-table__body-wrapper {
    order: 1;
}

/* 合计行位置修改结束*/
</style>
要实现Vue3 Element-Plus的el-table汇总单元格合并,你可以使用`span-method`属性来定义一个函数,该函数可以返回每个单元格需要合并数和列数。下面是一个示例代码: ```html <el-table :data="tableData" border style="width: 100%"> <el-table-column prop="date" label="日期" width="180"> </el-table-column> <el-table-column prop="name" label="姓名" width="180"> </el-table-column> <el-table-column prop="address" label="地址"> </el-table-column> <el-table-column label="合计" :span-method="objectSpanMethod"> <template #default="{ rows, row, column, $index }"> <span v-if="$index === 0">{{ row.total }}</span> </template> </el-table-column> </el-table> ``` 在上面的代码中,我们定义了一个`objectSpanMethod`方法,并将其赋值给`span-method`属性。这个方法接收四个参数:`{ rows, row, column, $index }`。其中`rows`是当前列的所有数据,`row`是当前数据,`column`是当前列数据,`$index`是当前的索引。 下面是`objectSpanMethod`方法的实现: ```js methods: { objectSpanMethod({ row, column, rowIndex, columnIndex }) { if (columnIndex === 3) { if (rowIndex === 0) { return { rowspan: this.tableData.length, colspan: 1 }; } else { return { rowspan: 0, colspan: 0 }; } } } } ``` 在上面的代码中,我们检查当前列是否为第四列(即“合计”列),如果是,我们检查当前是否为第一。如果是,我们返回一个对象`{ rowspan: this.tableData.length, colspan: 1 }`,其中`rowspan`表示当前单元格需要合并数,`colspan`表示当前单元格需要合并的列数。如果当前不是第一,则返回一个空对象`{ rowspan: 0, colspan: 0 }`,表示当前单元格不需要合并。 这样,我们就可以实现Vue3 Element-Plus的el-table汇总单元格合并了。
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值