el-table total row cell merge, cell style modification

1. Target effect

        The source code is placed below, just copy and paste

        (1) The total line is placed in the head, and the font color becomes thicker, and the background color of the total line becomes thicker

        (2) The age of the total row is calculated as the average value and the font color is green, and the property is calculated as the total and the font color is red 

2. Principle

2.1. The show-summary total line in el-table is placed at the end by default

        Just add the following css: parent selector /deep/ child selector to achieve style penetration

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

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

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

2.2. Modify the overall style of the total row

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

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

2.3. Summary method: :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 display the information of each column, which is an array of objects

        data is the information of each row, and it is also an object array, not counting the total row!

        sums is the total line,which is a tuple in typescript , that is, elements of different types can be stored in the array

  

2.4, total row cell style

        2.4.1, css method

.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;
}

        Disadvantage: It is necessary to manually calculate the position of each column. Once the position of the column changes, it is not easy to maintain

        2.4.2, jsx way

        Return jsx in the total line, generate a VNode, and dynamically generate styles

 // 年龄计算平均值(绿色)
                    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 returns VNode

         

2.5. Total row cell merge

        2.5.1, the way of other people's blog (error will be reported)        

 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, the method of merging rows in elementUI

        :span-method does not include total lines

        2.5.3. The method of this article ( recommended )

                Transformation on the basis of method 1:

 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)
            }
        }
    },

                Why is this possible?              

        Vue recommends using template to create HTML. But not real DOM nodes. Vue will first use the render function in the object to generate a virtual DOM node and mount it . The mounted real DOM is rendered asynchronously , and it is also rendered asynchronously after the state is modified . The document.querySelectorAll operation is defined as a synchronous task in the code , and the event queue should be:

        Synchronous queue: Get dom elements
        Asynchronous queue: Convert from virtual node to real node and render
        According to the execution process of synchronous first and then asynchronous , cells cannot be merged

        Use setTimeout to place elements in an asynchronous queue for execution, and then get the dom elements after the page is loaded and you will be successful!

 

2.6. There are fixed columns in the total row

        When there are fixed columns in the total row, the following problems will occur:

        (1) The total row in the fixed column ran to the bottom

        (2) The effect of merging cells disappears

 

 

        Add the following css and modify some 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;

}

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

    

 

        The final effect is as follows:

3. Source code

       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>

Guess you like

Origin blog.csdn.net/weixin_42375707/article/details/131260574