我是一个后端开发,所以我知道对于一个后端来说,去写这种东西是有多烦。所以把这个纵向合并单元格的功能,封装成一个通用方法,希望能起到抛砖引玉的作用。

ElementUI表格是提供单元格合并的功能的,笔者在实际开发过程中,有遇到业务场景,要求纵向同值合并。以下是代码示例。

  • util.js

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    /**
    * 生成el-table纵向合并相同值单元格的对象
    * @param rows 表格数据
    * @param prop 判断相同值的属性
    * @param obj el-table调用合并方法的回调
    */
    export const calcMergeObj = function(rows, props, {
    row,
    column,
    rowIndex,
    columnIndex
    }) {
    if (row['merge_mark_' + props.join('#')] === undefined) {
    const unionKey = unionKeyGenerator(row, props)
    let cnt = 0
    for (let i = rowIndex; i < rows.length; i++) {
    if (unionKeyGenerator(rows[i], props) === unionKey) {
    cnt++
    } else {
    break
    }
    }
    rows[rowIndex]['merge_mark_' + props.join('#')] = cnt
    // 给接下来的几行打隐藏行标记,即rowspan=0 colspan=0
    for (let idx = 1; idx < cnt; idx++) {
    rows[rowIndex + idx]['merge_mark_' + props.join('#')] = 0
    }
    }

    const mergeRowObj = {
    rowspan: row['merge_mark_' + props.join('#')],
    colspan: row['merge_mark_' + props.join('#')] > 0 ? 1 : 0
    }
    return mergeRowObj
    }

    const unionKeyGenerator = function(row, props) {
    let uKey = ''
    for (const prop of props) {
    uKey += row[prop] + '#'
    }
    return uKey
    }

  • index.vue

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    <template>
    <div class="main">
    <el-table
    :data="tableData"
    border
    size="mini"
    :span-method="objectMergeRow"
    >
    <el-table-column label="属性a" prop="a" align="center" />
    <el-table-column label="属性b" prop="b" align="center" />
    <el-table-column
    label="属性c"
    prop="c"
    align="center"
    show-overflow-tooltip
    />
    </el-table>
    </div>
    </template>

    <script>
    import { calcMergeObj } from "./util.js";
    export default {
    name: "merge-demo",
    data() {
    return {
    tableData: [
    { a: 1, b: "b1", c: "c3" }, //以c为判断依据,那么第1-3行c列合并
    { a: 1, b: "b2", c: "c3" },
    { a: 2, b: "b2", c: "c3" }, //以a+b为判断依据,那么b列第2行,第3行不能合并
    { a: 3, b: "b3", c: "c2" },
    { a: 3 /* */, b: "b3", c: "c3" },
    ],
    };
    },
    methods: {
    objectMergeRow(obj) {
    if (obj.columnIndex === 0) {
    return calcMergeObj(this.tableData, ["a"], obj);
    }
    if (obj.columnIndex === 1) {
    return calcMergeObj(this.tableData, ["a", "b"], obj);
    }
    if (obj.columnIndex === 2) {
    return calcMergeObj(this.tableData, ["c"], obj);
    }
    },
    },
    };
    </script>

    <style lang="scss" scoped>
    ::v-deep .el-table {
    th {
    font-size: 12px !important;
    border-color: #e6e6e6 !important;
    font-weight: bold !important;
    border-bottom: 1px solid #e6e6e6 !important;
    background-color: #f2f2f2 !important;
    padding: 4px 0 !important;
    line-height: 26px !important;
    height: 26px !important;
    }

    td {
    font-size: 12px !important;
    border-color: #e6e6e6 !important;
    line-height: 32px !important;
    padding: 4px 0 !important;
    }
    }
    </style>

  • 效果如下图所示

    ElementUI合并单元格效果