elementui完美做到table动态复杂合并行、合并列,适用于vue2、vue3

本人呕心沥血完成的,希望能多多转发,给个点赞,感谢个位大佬



此项目包括两种方法,方法一是纯前端实现,方法二是纯后端实现



废话不多说,直接先上效果图

完整代码如下:


方法一:

方法一是纯前端来实现复杂的合并行合并列的功能

```<template>

    <div class="">

        <el-table

            ref="mutipleTable"

            border

            stripe

            :data="tableData"

            style="width: 100%"

            :span-method="objectSpanMethod"

            :cell-style="cellStyle"

        >

            <el-table-column v-for="item in columns" :key="item.prop" :prop="item.prop" :label="item.label" :min-width="item.minWidth" />

        </el-table>

    </div>

</template>

<script>

export default {

    data() {

        return {

            // 需要动态合并列的配置(一般是由接口返回来,看自己需要)

            hangLabels: {

                // 要合并的第几行

                hang5: {

                    // 要合并的表头,要跟前端对应上

                    labels: ['测试3', '测试4', '测试5', '测试6', '测试7'],

                    // 要合并的单元格

                    subtotals: ['微信小程序小计:', '支付宝小程序小计:'],

                    // 要合并的单元格的接口返回字段

                    attr: 'a3'

                },

                hang6: {

                    labels: ['测试2', '测试3', '测试4', '测试5', '测试6', '测试7'],

                    subtotals: ['小合计:', '小合计1:'],

                    attr: 'a2'

                },

                hang7: {

                    labels: ['测试1', '测试2', '测试3', '测试4', '测试5', '测试6', '测试7'],

                    subtotals: ['大合计:'],

                    attr: 'a1'

                }

            },

            // 表头配置

            columns: [

                {

                    prop: 'a1',

                    minWidth: '150px',

                    label: '测试1'

                },

                {

                    prop: 'a2',

                    minWidth: '150px',

                    label: '测试2'

                },

                {

                    prop: 'a3',

                    minWidth: '150px',

                    label: '测试3'

                },

                {

                    prop: 'a4',

                    minWidth: '150px',

                    label: '测试4'

                },

                {

                    prop: 'a5',

                    minWidth: '150px',

                    label: '测试5'

                },

                {

                    prop: 'a6',

                    minWidth: '150px',

                    label: '测试6'

                },

                {

                    prop: 'a7',

                    minWidth: '120px',

                    label: '测试7'

                },

                {

                    prop: 'a8',

                    minWidth: '120px',

                    label: '测试8'

                },

                {

                    prop: 'a9',

                    minWidth: '120px',

                    label: '测试9'

                },

                {

                    prop: 'a10',

                    minWidth: '120px',

                    label: '测试10'

                },

                {

                    prop: 'a11',

                    minWidth: '120px',

                    label: '测试11'

                }

            ],

            // 接口返回数据

            tableData: [

                {

                    a1: '内容1',

                    a2: '内容2',

                    a3: '微信小程序',

                    a4: 'T000010345',

                    a5: 'T1000000148',

                    a6: '内容3',

                    a7: '220',

                    a8: '43'

                },

                {

                    a1: '内容1',

                    a2: '内容2',

                    a3: '微信小程序',

                    a4: 'T000010346',

                    a5: 'T1000000149',

                    a6: '内容4',

                    a7: '80',

                    a8: '5'

                },

                {

                    a1: '内容1',

                    a2: '内容2',

                    a3: '微信小程序小计:',

                    a4: '微信小程序小计:',

                    a5: '微信小程序小计:',

                    a6: '微信小程序小计:',

                    a7: '微信小程序小计:',

                    a8: '44'

                },

                {

                    a1: '内容1',

                    a2: '小合计:',

                    a3: '小合计:',

                    a4: '小合计:',

                    a5: '小合计:',

                    a6: '小合计:',

                    a7: '小合计:',

                    a8: '76'

                },

                {

                    a1: '内容1',

                    a2: '内容5',

                    a3: '支付宝小程序',

                    a4: 'T000010188',

                    a5: 'T1000000170',

                    a6: '内容6',

                    a7: '220',

                    a8: '43'

                },

                {

                    a1: '内容1',

                    a2: '内容5',

                    a3: '支付宝小程序',

                    a4: 'T000010189',

                    a5: 'T1000000145',

                    a6: '内容7',

                    a7: '220',

                    a8: '43'

                },

                {

                    a1: '内容1',

                    a2: '小合计1:',

                    a3: '小合计1:',

                    a4: '小合计1:',

                    a5: '小合计1:',

                    a6: '小合计1:',

                    a7: '小合计1:',

                    a8: '76'

                },

                {

                    a1: '大合计:',

                    a2: '大合计:',

                    a3: '大合计:',

                    a4: '大合计:',

                    a5: '大合计:',

                    a6: '大合计:',

                    a7: '大合计:',

                    a8: '56'

                }

            ],

            // 统计合并多少行

            needMergeArr: ['a1', 'a2', 'a3'], // 有合并项的列

            rowMergeArrs: {} // 包含需要一个或多个合并项信息的对象

        }

    },

    mounted() {

        // 请求接口

        this.getList()

    },

    updated() {

        // 每次更新会重新对 Table 进行重新布局

        this.$nextTick(() => {

            if (this.$refs.mutipleTable !== undefined) {

                this.$refs.mutipleTable.doLayout()

            }

        })

    },

    methods: {

        // 请求接口

        getList() {

            // 处理合并行数据

            this.rowMergeArrs = this.rowMergeHandle(this.needMergeArr, this.tableData)

        },

        // 单元格样式,主要是针对要合并列的第一个单元格(有其他需要的可自行更改)

        cellStyle({ row, column }) {

            for (const { labels, subtotals, attr } of Object.values(this.hangLabels)) {

                const columnIndex = labels.indexOf(column.label)

                if (columnIndex !== -1 && subtotals.includes(row[attr])) {

                    if (columnIndex === 0) {

                        return { 'text-align': 'left' }

                    }

                }

            }

            return {} // 默认返回空样式

        },

        /**

* @description 实现合并行或列

* @param row:Object 需要合并的列name 如:'name' 'id'

* @param column:Object 当前行的行数,由合并函数传入

* @param rowIndex:Number 当前列的数据,由合并函数传入

* @param columnIndex:Number 当前列的数据,由合并函数传入

*

* @return 函数可以返回一个包含两个元素的数组,第一个元素代表rowspan,

* 第二个元素代表colspan。 也可以返回一个键名为rowspan和colspan的对象

*/

        objectSpanMethod({ row, column, rowIndex, columnIndex }) {

            // 合并列

            for (const { labels, subtotals, attr } of Object.values(this.hangLabels)) {

                const columnIndex = labels.indexOf(column.label)

                if (columnIndex !== -1 && subtotals.includes(row[attr])) {

                    return columnIndex === 0 ? [1, labels.length] : [0, 0]

                }

            }

            // 合并行

            for (const key in this.rowMergeArrs) {

                if (column.property == key) {

                    const _row = this.rowMergeArrs[key].rowArr[rowIndex]

                    const _col = _row > 0 ? 1 : 0

                    return [_row, _col]

                }

            }

        },

        /**

* @description 根据数组将指定对象转化为相应的数组

* @param arr:Array[String] 必填 必须是字符串形式的数组

* @param data:Array 必填 需要转化的对象

*/

        rowMergeHandle(arr, data) {

            if (!Array.isArray(arr) && !arr.length) return false

            if (!Array.isArray(data) && !data.length) return false

            const needMerge = {}

            arr.forEach(i => {

                needMerge[i] = {

                    rowArr: [],

                    rowMergeNum: 0

                }

                data.forEach((item, index) => {

                    if (index === 0) {

                        needMerge[i].rowArr.push(1)

                        needMerge[i].rowMergeNum = 0

                    } else {

                        if (item[i] === data[index - 1][i]) {

                            needMerge[i].rowArr[needMerge[i].rowMergeNum] += 1

                            needMerge[i].rowArr.push(0)

                        } else {

                            needMerge[i].rowArr.push(1)

                            needMerge[i].rowMergeNum = index

                        }

                    }

                })

            })

            return needMerge

        }

    }

}

</script>

```



方法二:

方法二是纯后端来实现复杂的合并行合并列的功能

```

<template>

    <div class="">

        <el-table

            ref="mutipleTable"

            border

            stripe

            :data="tableData"

            style="width: 100%"

            :span-method="objectSpanMethod"

            :cell-style="cellStyle"

        >

            <el-table-column v-for="item in columns" :key="item.prop" :prop="item.prop" :label="item.label" :min-width="item.minWidth" />

        </el-table>

    </div>

</template>

<script>

export default {

    data() {

        return {

            // 表头配置

            columns: [

                {

                    prop: 'a1',

                    minWidth: '150px',

                    label: '测试1'

                },

                {

                    prop: 'a2',

                    minWidth: '150px',

                    label: '测试2'

                },

                {

                    prop: 'a3',

                    minWidth: '150px',

                    label: '测试3'

                },

                {

                    prop: 'a4',

                    minWidth: '150px',

                    label: '测试4'

                },

                {

                    prop: 'a5',

                    minWidth: '150px',

                    label: '测试5'

                },

                {

                    prop: 'a6',

                    minWidth: '150px',

                    label: '测试6'

                },

                {

                    prop: 'a7',

                    minWidth: '120px',

                    label: '测试7'

                },

                {

                    prop: 'a8',

                    minWidth: '120px',

                    label: '测试8'

                },

                {

                    prop: 'a9',

                    minWidth: '120px',

                    label: '测试9'

                },

                {

                    prop: 'a10',

                    minWidth: '120px',

                    label: '测试10'

                },

                {

                    prop: 'a11',

                    minWidth: '120px',

                    label: '测试11'

                }

            ],

            // 接口返回数据

            tableData: [

                {

                    a1: '内容1',

                    a2: '内容2',

                    a3: '微信小程序',

                    a4: 'T000010345',

                    a5: 'T1000000148',

                    a6: '内容3',

                    a7: '220',

                    a8: '43',

                    // 合并列和行的数据

                    mergeData: {

                        // 纯后端返回,[a,b]中的a代表行,b代表列具体可以参考elementui的合并行合并列的定义,是一样的

                        a1: [7, 1],

                        a2: [3, 1],

                        a3: [2, 1],

                        a4: [1, 1],

                        a5: [1, 1],

                        a6: [1, 1],

                        a7: [1, 1],

                        a8: [1, 1]

                    }

                },

                {

                    a1: '内容1',

                    a2: '内容2',

                    a3: '微信小程序',

                    a4: 'T000010346',

                    a5: 'T1000000149',

                    a6: '内容4',

                    a7: '80',

                    a8: '5',

                    // 合并列和行的数据

                    mergeData: {

                        a1: [0, 0],

                        a2: [0, 0],

                        a3: [0, 0],

                        a4: [1, 1],

                        a5: [1, 1],

                        a6: [1, 1],

                        a7: [1, 1],

                        a8: [1, 1]

                    }

                },

                {

                    a1: '内容1',

                    a2: '内容2',

                    a3: '微信小程序小计:',

                    a4: '微信小程序小计:',

                    a5: '微信小程序小计:',

                    a6: '微信小程序小计:',

                    a7: '微信小程序小计:',

                    a8: '44',

                    // 合并列和行的数据

                    mergeData: {

                        a1: [0, 0],

                        a2: [0, 0],

                        a3: [1, 5],

                        a4: [0, 0],

                        a5: [0, 0],

                        a6: [0, 0],

                        a7: [0, 0],

                        a8: [1, 1]

                    }

                },

                {

                    a1: '内容1',

                    a2: '小合计:',

                    a3: '小合计:',

                    a4: '小合计:',

                    a5: '小合计:',

                    a6: '小合计:',

                    a7: '小合计:',

                    a8: '76',

                    // 合并列和行的数据

                    mergeData: {

                        a1: [0, 0],

                        a2: [1, 6],

                        a3: [0, 0],

                        a4: [0, 0],

                        a5: [0, 0],

                        a6: [0, 0],

                        a7: [0, 0],

                        a8: [1, 1]

                    }

                },

                {

                    a1: '内容1',

                    a2: '内容5',

                    a3: '支付宝小程序',

                    a4: 'T000010188',

                    a5: 'T1000000170',

                    a6: '内容6',

                    a7: '220',

                    a8: '43',

                    // 合并列和行的数据

                    mergeData: {

                        a1: [0, 0],

                        a2: [2, 1],

                        a3: [2, 1],

                        a4: [1, 1],

                        a5: [1, 1],

                        a6: [1, 1],

                        a7: [1, 1],

                        a8: [1, 1]

                    }

                },

                {

                    a1: '内容1',

                    a2: '内容5',

                    a3: '支付宝小程序',

                    a4: 'T000010189',

                    a5: 'T1000000145',

                    a6: '内容7',

                    a7: '220',

                    a8: '43',

                    // 合并列和行的数据

                    mergeData: {

                        a1: [0, 0],

                        a2: [0, 0],

                        a3: [0, 0],

                        a4: [1, 1],

                        a5: [1, 1],

                        a6: [1, 1],

                        a7: [1, 1],

                        a8: [1, 1]

                    }

                },

                {

                    a1: '内容1',

                    a2: '小合计1:',

                    a3: '小合计1:',

                    a4: '小合计1:',

                    a5: '小合计1:',

                    a6: '小合计1:',

                    a7: '小合计1:',

                    a8: '76',

                    // 合并列和行的数据

                    mergeData: {

                        a1: [0, 0],

                        a2: [1, 6],

                        a3: [0, 0],

                        a4: [0, 0],

                        a5: [0, 0],

                        a6: [0, 0],

                        a7: [0, 0],

                        a8: [1, 1]

                    }

                },

                {

                    a1: '大合计:',

                    a2: '大合计:',

                    a3: '大合计:',

                    a4: '大合计:',

                    a5: '大合计:',

                    a6: '大合计:',

                    a7: '大合计:',

                    a8: '56',

                    // 合并列和行的数据

                    mergeData: {

                        a1: [1, 7],

                        a2: [0, 0],

                        a3: [0, 0],

                        a4: [0, 0],

                        a5: [0, 0],

                        a6: [0, 0],

                        a7: [0, 0],

                        a8: [1, 1]

                    }

                }

            ]

        }

    },

    updated() {

        // 每次更新会重新对 Table 进行重新布局

        this.$nextTick(() => {

            if (this.$refs.mutipleTable !== undefined) {

                this.$refs.mutipleTable.doLayout()

            }

        })

    },

    methods: {

        // 单元格样式,主要是针对要合并列的第一个单元格(有其他需要的可自行更改)

        cellStyle({ row, column }) {

            // 找到数组中列>1那一个单元格,就是需要改变的样式

            if (row['mergeData'][column.property] && row['mergeData'][column.property][1] && row['mergeData'][column.property][1] > 1) {

                return { 'text-align': 'left' }

            } else {

                return {}

            }


        },

        /**

* @description 实现合并行或列

* @param row:Object 需要合并的列name 如:'name' 'id'

* @param column:Object 当前行的行数,由合并函数传入

* @param rowIndex:Number 当前列的数据,由合并函数传入

* @param columnIndex:Number 当前列的数据,由合并函数传入

*

* @return 函数可以返回一个包含两个元素的数组,第一个元素代表rowspan,

* 第二个元素代表colspan。 也可以返回一个键名为rowspan和colspan的对象

*/

        objectSpanMethod({ row, column }) {

            // 直接返回后端给的对应字段的单元格数据

            return row['mergeData'][column.property]

        }

    }

}

</script>

```

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容