使用小技巧实现 el-table 组件的合并行功能,ElementUI和EleMentPlus都适用

有时遇到一些需求,需要实现Element UI或Element Plus中,el-tabled 组件合并单元格的功能,稍微了解一下它的数据格式,不难可以写出比合并方法。但是在鼠标经过单元行时,会出现高亮的行与鼠标经过的行不一致的BUG。因此还需要实现 @cell-mouse-enter 和  @cell-mouse-leave 这两个方法,才可解决此问题。

一、示例代码(/src/views/Example/MergeCell/index.vue)

<template>
  <div class="merge-cell">
    <div class="merge-cell-navbar">记录一下 el-table 合并行小技巧</div>
 
    <div class="merge-cell-content">
      <div class="merge-cell-content-container">
        <el-table
          :data="tableData"
          border
          height="100%"
          :header-cell-style="
            {
              padding: '4px', // 设置Table表头单元内边距
              backgroundColor: '#e7f0ff', // 设置Table表头背景颜色
              borderColor: '#b6d1ff', // 设置Table表头边框颜色
              color: '#000', // 设置Table表头文字颜色
              fontSize: '13px', // 设置Table表头文字大小
              fontWeight: 'normal', // 设置Table表头文字粗细
            }
          "
          :span-method="handleSpanMethod"
          :row-class-name="handleRowClassName"
          @cell-mouse-enter="handleCellMouseEnter"
          @cell-mouse-leave="handleCellMouseLeave"
        >
          <el-table-column prop="zone" label="GameZone / 服务器区域 / 游戏区域" align="center" />
          <el-table-column prop="career" label="职业" width="180" align="center" />
          <el-table-column label="英雄" align="center">
            <el-table-column prop="hero" label="英雄姓名" width="280" align="center" />
            <el-table-column prop="firstSkill" label="一技能" width="220" align="center" />
            <el-table-column prop="secondSkill" label="二技能" width="220" align="center" />
            <el-table-column prop="thirdSkill" label="三技能" width="220" align="center" />
            <el-table-column label="操作" width="180" align="center">
              <template #default="scope">
                <el-tooltip effect="dark" content="收藏" placement="top" :enterable="false" :hide-after="0" @click="handleEditClick(scope.$index, scope.row)">
                  <el-button size="small" circle>
                    <el-icon size="18"><StarFilled /></el-icon>
                  </el-button>
                </el-tooltip>
              </template>
            </el-table-column>
          </el-table-column>
        </el-table>
      </div>
    </div>
  </div>
</template>
 
<script>
export default {
  data: () => ({
    tableData: [
      {
        zone: "王者一区",
        career: "坦克",
        hero: "亚瑟",
        firstSkill: "誓约之盾",
        secondSkill: "回旋打击",
        thirdSkill: "圣剑裁决",
      },
      {
        zone: "王者一区",
        career: "坦克",
        hero: "吕布",
        firstSkill: "方天画斩",
        secondSkill: "贪狼之握",
        thirdSkill: "魔神降世",
      },
      {
        zone: "王者一区",
        career: "坦克",
        hero: "项羽",
        firstSkill: "无畏冲锋",
        secondSkill: "破釜沉舟",
        thirdSkill: "霸王斩杀",
      },
      {
        zone: "王者一区",
        career: "战士",
        hero: "云缨",
        firstSkill: "断月",
        secondSkill: "追云",
        thirdSkill: "逐星",
      },
      {
        zone: "王者一区",
        career: "战士",
        hero: "赵怀真",
        firstSkill: "拨云见明",
        secondSkill: "气定神凝",
        thirdSkill: "阴阳逆转",
      },
      {
        zone: "王者二区",
        career: "刺客",
        hero: "镜",
        firstSkill: "开锋",
        secondSkill: "裂空",
        thirdSkill: "见影",
      },
      {
        zone: "王者二区",
        career: "刺客",
        hero: "澜",
        firstSkill: "破浪",
        secondSkill: "断空",
        thirdSkill: "处决",
      },
      {
        zone: "王者二区",
        career: "刺客",
        hero: "李白",
        firstSkill: "将进酒",
        secondSkill: "神来之笔",
        thirdSkill: "青莲剑歌",
      },
      {
        zone: "王者三区",
        career: "法师",
        hero: "妲己",
        firstSkill: "灵魂冲击",
        secondSkill: "偶像魅力",
        thirdSkill: "女王崇拜",
      },
      {
        zone: "王者三区",
        career: "射手",
        hero: "后羿",
        firstSkill: "多重箭矢",
        secondSkill: "落日余晖",
        thirdSkill: "灼日之矢",
      },
      {
        zone: "王者三区",
        career: "射手",
        hero: "鲁班7号",
        firstSkill: "河豚手雷",
        secondSkill: "无敌鲨嘴炮",
        thirdSkill: "空中支援",
      },
      {
        zone: "王者三区",
        career: "辅助",
        hero: "孙膑",
        firstSkill: "时空爆弹",
        secondSkill: "时之波动",
        thirdSkill: "时光流逝",
      },
      {
        zone: "王者三区",
        career: "辅助",
        hero: "庄周",
        firstSkill: "化蝶",
        secondSkill: "蝴蝶效应",
        thirdSkill: "天人合一",
      },
    ],
 
    first_row: {},
    second_row: {},
  }),
  methods: {
    /**
     * 合并单元格句柄方法
     */
    handleSpanMethod({
      row, // 行
      column, // 列
      rowIndex, // 行索引
      columnIndex, // 列索引
    }) {
      if (columnIndex === 0 || columnIndex === 1) {
        // 获取当前单元格的值
        const currentValue = row[column.property];
 
        // 获取上一行相同列的值
        const preRow = this.tableData[rowIndex - 1];
        const preValue = preRow ? preRow[column.property] : null;
 
        // 如果当前值和上一行的值相同,则将当前单元格隐藏
        if (currentValue === preValue) {
          return { rowspan: 0, colspan: 0 };
        } else {
          // 否则计算当前单元格应该跨越多少行
          let rowspan = 1;
          for (let i = rowIndex + 1; i < this.tableData.length; i++) {
            const nextRow = this.tableData[i];
            const nextValue = nextRow[column.property];
            if (nextValue === currentValue) {
              rowspan++;
            } else {
              break;
            }
          }
          return { rowspan, colspan: 1 };
        }
      }
    },
 
    /**
     * 鼠标移入表格事件句柄方法
     */
    handleCellMouseEnter(row, column, cell, event) {
      this.second_row = this.tableData.filter((item) => {
        return this.filterSameKeys(item, row, ["zone", "career"]);
      })[0];
 
      this.first_row = this.tableData.filter((item) => {
        return this.filterSameKeys(item, row, ["zone"]);
      })[0];
    },
 
    /**
     * 鼠标移出表格事件句柄方法
     */
    handleCellMouseLeave() {
      this.currentIndex = "";
      this.currentColumnIndex = "";
      this.first_row = {};
      this.second_row = {};
    },
 
    /**
     * 根据 keys 数组所有字段去做合并
     */
    filterSameKeys(item, row, keys) {
      let flag = true;
      keys.forEach((key) => {
        flag = flag && item[key] === row[key];
      });
      return flag;
    },
    
    /**
     * 给表格行添加自定义类名
     */
    handleRowClassName({ row }) {
      let flag1 = this.first_row == row ? "first_row" : "";
      let flag2 = this.second_row == row ? "second_row" : "";
      return `${flag1} ${flag2}`;
    },
  },
};
</script>
 
<style lang="less" scoped>
  .merge-cell {
    display: flex;
    flex-direction: column;
    position: relative;
    width: 100%;
    height: 100%;
    overflow: hidden;
 
    .merge-cell-navbar {
      position: relative;
      width: 100%;
      height: 100px;
      background-color: #686868;
      text-align: center;
      line-height: 100px;
      color: #fff;
      font-size: 25px;
    }
 
    .merge-cell-content {
      position: relative;
      flex: 1;
      padding: 100px;
      overflow: hidden;
 
      .merge-cell-content-container {
        position: relative;
        width: 100%;
        height: 100%;
        overflow: auto;
      }
    }
 
    :deep(.el-table) {
 
      td .cell {
        padding: 2.5px 0;
        color: #686868;
        font-size: 13px;
      }
 
      .first_row td:nth-child(1),
      .second_row td:nth-child(1),
      .first_row.second_row td:nth-child(2) {
          background: #f5f7fa !important;
      }
    }
 
    /* ^ 设置Table表格边框颜色 */
    :deep(.el-table--border) {
      &::before {
        background-color: #b6d1ff;
      }
      &::after {
        background-color: #b6d1ff;
      }
      .el-table__cell {
        border-color: #b6d1ff;
      }
      .el-table__inner-wrapper {
        &::before {
          background-color: #b6d1ff;
        }
        &::after {
          background-color: #b6d1ff;
        }
        .el-table__border-left-patch {
          background-color: #b6d1ff;
        }
      }
    }
    /* / 设置Table表格边框颜色 */
  }
</style>

二、效果如下 ~

三、转载地址:https://juejin.cn/post/6930897196732645390

猜你喜欢

转载自blog.csdn.net/Cai181191/article/details/130607177
今日推荐