关于el-table开发时的一些常见问题(待更新)

366 阅读12分钟

我们在使用饿了么组件的时候经常经常经常会用到el-table组件,所以会经常遇到一些问题,这个帖子统计了我工作到现在目前为止觉得出现比较频繁的一些问题或者使用。

如果有不对的地方或者有更好的方法望指出,共同进步。

1.使用fixed以后拖不动横向滚动条

我们使用fixed属性使列固定的时候,会发现固定列下方的横向滚动条是拖不动的,但是我们只要加上一个css以后就可以了。

::v-deep .el-table--scrollable-x .el-table__body-wrapper {
  z-index: 1;
}

这应该是遇到最多的场景了,毕竟经常会出现表头很多,需要在拖动横向滚动条的时候让某一列固定住的情况。

2.动态切换表头的时候出现表头闪烁的问题

我们在使用v-if去动态的切换表头的时候会发现表头会闪烁一下,这会导致用户体验不佳,其实表头闪烁的原因也很简单,这是因为表格在渲染额时候要重新计算表头的高度,我们只需要给表头高度给固定死就好了。

::v-deep .el-table .el-table__header-wrapper .cell {
  height: 23px !important;
}

3.表格合计行的使用

1. 默认合计行

el-table表格自己就有合计行功能,通过show-summary属性就可以开启默认行。

    <el-table
      ref="myTable"
      :data="tableData"
      height="30%"
      border
      stripe
      :cell-style="{ textAlign: 'center' }"
      :header-cell-style="{ textAlign: 'center' }"
      show-summary
    >
      <el-table-column label="名称" prop="name"></el-table-column>
      <el-table-column label="测试1" prop="test1"></el-table-column>
      <el-table-column label="测试2" prop="test2"></el-table-column>
      <el-table-column label="测试3" prop="test3"></el-table-column>
      <el-table-column label="测试4" prop="test4"></el-table-column>
    </el-table>

效果展示:

1745824237766.png

效果是可以呈现出来的,我们来总结一下默认合计行的几个特点:

  1. 第一列不进行数据求合操作,而是显示合计二字,这个可以根据sum-text属性进行修改。

1745824522831.png 1745824575446.png

  1. 默认合计行的单元格样式不受cell-style样式的影响,图中也看出来他们没居中,所以需要单独设置样式。
  2. 在进行数据求和操作的时候,如果该列都没有数据,就默认为0(第二列);如果该列数据有的数据是数字有的是文字,会只进行数字的求和而忽略那些文字的(第三列);如果该列的数据都不是数字,合计的数据就是空的(第四列);如果该列数据都是数字就正常求和(第五列)。

2.修改合计行的样式

前面说了合计行的样式是不受cell-style样式的影响,因为此时el-table主要由 headerWrapperbodyWrapperfooterWrapper 三个部分组成。,也就是表格表头、表格主体内容、表格底部合计行,换成css类名的话就是el-table__header-wrapperel-table__body-wrapperel-table__footer-wrapper

1745828013619.png

cell-style的样式是作用于表格主体内容的,不会影响到表格底部合计行,所以我们需单独的去处理。

合计行整体修改

::v-deep .el-table .el-table__footer-wrapper tbody tr td {
  text-align: center;
}

这里就能看明白了吧,tr是到合计行的类名,td是到合计行的单元格的类名。

1745828097804.png

但是这样是对合计行整行进行样式修改,或者是对合计行的所有单元格进行统一修改。

合计行某个单元格进行修改

有两种方式,一种是css的形式,还有一种是jsx的形式。

1.css形式

通过:nth-child(n)的方式对某一个单元格进行修改。

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

1745895476940.png

但是这样比较死板,因为要根据:nth-child(n)去固定在某一列进行生效,如果顺序改变就会出现错误。

2.jsx形式

这个待会讲自定义单元行的时候一起讲。

3.合计行出现了表格滚动条下方

在列数过多导致出现横向滚动条的时候,我们会发现合计行出现在了滚动条的下方。出现这样的原因其实也很简单,我们前面说了此时的表格由三部分组成,而滚动条其实是放在bodyWrapper这个结构上面的,而合计行是在footerWrapper这个结构上,所以说合计行会在滚动条下面。只不过底层做了逻辑,让bodyWrapper这个结构滚动的同时也可以带动footerWrapper结构和headerWrapper结构滚动,但是这样合计行在滚动条下方也是很不合理的。

image.png

那么怎么解决这个问题呢?

其实合计行原本也是有滚动条的,只是被默认隐藏了而已,我们可以隐藏bodyWrapper结构的滚动条,而展示footerWrapper结构的滚动条,这样一来,滚动条就会在合计行的下面。

::v-deep .el-table--scrollable-x .el-table__body-wrapper {
  overflow-x: hidden !important;
  z-index: 2 !important;
}
::v-deep .el-table__footer-wrapper {
  overflow-x: auto;
}

1745830958295.png

只是这样我们滑动滚动条的时候只能带动合计行滚动,而带不动表格主体内容和表格表头跟着滚动,所以我们也需要做一些修改,让footerWrapper结构滚动的同时也可以让bodyWrapper这个结构滚动(原本的底层逻辑bodyWrapper会带着headerWrapper结构滚动,所以这里我们不用管headerWrapper结构)。

我们可以监听footerWrapper结构滚动的事件,获取footerWrapper结构滚动的距离,然后去去手动修改bodyWrapper结构滚动条滚动的距离就可以了。

mounted() {
    let tableBody = this.$refs.myTable.$refs.footerWrapper
    tableBody.addEventListener('scroll', () => {
      // 滚动距离
      const scrollLeft = tableBody.scrollLeft
      this.$refs.myTable.$refs.bodyWrapper.scrollLeft = scrollLeft
    })
  },

这样一来我们滑动合计行的滚动条就可以带动合计行,表格主体内容,表格表头同时滚动了。

4.合计行不展示,只有缩放/变大窗口或者F12弹出后台时才展示

不展示的原因是因为如果表格刚开始是没有数据的,那么就不会展示合计行,等获取到数据的时候,表格不会重新渲染合计行的dom,所以该合计行还是不展示,缩放窗口或者弹出后台时会导致页面重新渲染,此时合计行才会渲染出来。

比如下面这个,就是刚开始表格没有数据,我们点击按钮获取数据以后,会发现合计行是不会展示的。

image.png

image.png

我们可以在获取数据以后调用el-tabledoLayout()方法去重新渲染整个表格的dom,就可以让合计行展示出来了,不过记得要在外面加一个``this.$nextTick()。

    // 获取数据的方法
    getData() {
      this.tableData = [
        {
          test1: "",
          test2: "阿巴阿巴",
          test3: "加强锤石",
          test4: "1",
          name: "yueliang",
        },
        {
          test1: "",
          test2: "2",
          test3: "削一下瑞文",
          test4: "2",
          name: "月亮",
        },
      ];
      this.$nextTick(() => {
        this.$refs.myTable.doLayout();
      });
    },

此时就可以在获取数据的时候展示合计行了。

image.png

image.png

当然我们在数据更新的生命周期函数钩子里操作也是可以的。

  updated() {
    this.$nextTick(() => {
      this.$refs.myTable.doLayout();
    });
  },

5.自定义合计行

前面说的都是el-table的默认合计行,除此之外也可以支持自定义合计行。我们通过show-summary属性开启合计行功能以后,再使用summary-method属性去使用自定义合计行方法。

    <el-table
      ref="myTable"
      :data="tableData"
      height="30%"
      border
      stripe
      :cell-style="{ textAlign: 'center' }"
      :header-cell-style="{ textAlign: 'center' }"
      show-summary
      :summary-method="getSummaries"
    >
      <el-table-column label="名称" prop="name"></el-table-column>
      <el-table-column label="测试1" prop="test1"></el-table-column>
      <el-table-column label="测试2" prop="test2"></el-table-column>
      <el-table-column label="测试3" prop="test3"></el-table-column>
      <el-table-column label="测试4" prop="test4"></el-table-column>
    </el-table>

我们自定义合计行的方法getSummaries接收一个参数,参数是一个对象,里面有两个属性columnsdata,其中columns是表格表头的数据,data是表格的内容数据。

    getSummaries(param) {
      // columns 是一个数组,每一项就是每一列表头的内容
      // data 是一个数组,是表格数据,每一项就是每一行row的数据
      const { columns, data } = param;
      // sums 是合计行的数据,是一个普通数组,数组每一项内容就是合计行按照顺序展示的内容
      const sums = [];
      // 对表头进行遍历,对每一列进行操作
      columns.forEach((column, index) => {
        // 这里是设置合计行第一列内容,一般是总计或者合计,这里是根据index判断的,也可以根据prop判断 if(column.property === "name")
        if (index === 0) {
          sums[index] = "合计";
        } else if (
          // 这里是自己需要合计的表头,这里是根据index判断,如果为了防止以后顺序打乱,也可以用prop去判断
          index > 0
        ) {
          // values 是该列所有数据组成的数组
          let values = data.map((item) => {
            // Number包裹一层会把字符串转换成数值型,方便下面合计
            return Number(item[column.property]);
          });
          values = values.filter((item) => {
            // 如果不是数字,Number包裹以后会变成NaN,会影响合计,所以这里做个筛选,把不是NaN的筛选出来进行合计
            if (item) {
              return true;
            }
          });
          // 这是把该列的所有值都相加再一起
          sums[index] = values.reduce((prev, cur) => {
            return Number(prev) + Number(cur);
          }, 0);
          if (index === 6) {
            sums[index] = (sums[index] / values.length).toFixed(2);
          }
        } else {
          // 这里是不需要合计的列 设置展示内容为 ---
          sums[index] = "---";
        }
      });
      return sums;
    },

我这个注释写的还是很详细的,自己慢慢看看,如果有什么平均价格这种需求,就是合计以后还要再除以总数,可以再加上这一段代码。

image.png

补充上面说的jsx形式去修改单元格样式

其实也就是在原有的基础上做一些修改,用jsx的方式去赋值一个dom结构,然后通过在上面添加类名的方式去修改单元格样式。

    getSummaries(param) {
      const { columns, data } = param;
      const sums = [];
      columns.forEach((column, index) => {
        if (index === 0) {
          sums[index] = "合计";
        } else if (index > 0) {
          let values = data.map((item) => {
            return Number(item[column.property]);
          });
          values = values.filter((item) => {
            if (item) {
              return true;
            }
          });
          let value = values.reduce((prev, cur) => {
            return Number(prev) + Number(cur);
          }, 0);
          // jsx形式去赋值一个dom结构,在dom结构上写类名
          sums[index] = <span class={"green"}>{value}</span>;
        } else {
          sums[index] = "---";
        }
      });
      return sums;
    },
.green {
    color: lightgreen;
    font-weight: bolder;
}

6.合计行单元格合并

监视表格数据,如果表格数据有改变,比如获取到数据或者修改了数据,就进行操作,获取到合计行的dom,用dom操作的方式去合并单元格。

  watch: {
    // 监视表格数据
    tableData: {
      immediate: true,
      handler() {
        setTimeout(() => {
          // 获取合计行dom
          const tds = document.querySelectorAll(
            ".el-table__footer-wrapper tr>td"
          );
          // 如果合并前面两个单元格,就设置tds[0].colSpan = 2,具体情况自己改动一下
          tds[0].colSpan = 2;
          // 设置单元格居中
          tds[0].style.textAlign = "center";
          // 把被合并的单元格给隐藏,因为是合并前面两个单元格,所以把第二个单元格隐藏
          tds[1].style.display = "none";
        }, 0);
      },
    },
  },

4.表格前端分页

这种情况也很多,当数据过多的时候,表格会渲染的很慢,导致页面很卡,这时候就要对表格进行分页,分页有两种方式,一种是前端分页,还有一种是后端分页。

其实这个很简单,记录下来也单纯是想以后遇到直接拿来用懒得想。

这是原页面:

1746520852262.png

    <el-table
      ref="myTable"
      :data="tableData"
      height="30%"
      border
      stripe
      :cell-style="{ textAlign: 'center' }"
      :header-cell-style="{ textAlign: 'center' }"
    >
      <el-table-column label="名称" prop="name"></el-table-column>
      <el-table-column label="测试1" prop="test1"></el-table-column>
      <el-table-column label="测试2" prop="test2"></el-table-column>
      <el-table-column label="测试3" prop="test3"></el-table-column>
      <el-table-column label="测试4" prop="test4"></el-table-column>
    </el-table>

我们分页也会用到饿了么UI的el-pagination组件,具体用法自己去官网看,很简单。

1.前端分页

<template>
  <div class="screen-view">
    <el-table
      ref="myTable"
      :data="showTableData"
      height="30%"
      border
      stripe
      :cell-style="{ textAlign: 'center' }"
      :header-cell-style="{ textAlign: 'center' }"
    >
      <el-table-column label="名称" prop="name"></el-table-column>
      <el-table-column label="测试1" prop="test1"></el-table-column>
      <el-table-column label="测试2" prop="test2"></el-table-column>
      <el-table-column label="测试3" prop="test3"></el-table-column>
      <el-table-column label="测试4" prop="test4"></el-table-column>
    </el-table>
    <el-pagination
      @size-change="handleSizeChange"
      @current-change="handleCurrentChange"
      :current-page.sync="currentPage"
      :page-sizes="[10, 20, 30, 50]"
      :page-size="pageSize"
      layout="prev, pager, next, jumper, total, sizes"
      :total="tableData.length"
      class="mt10"
    >
    </el-pagination>
  </div>
</template>

<script>
export default {
  data() {
    return {
      tableData: [
        { name: "1", test1: "1", test2: "1", test3: "1", test4: "1" },
        { name: "2", test1: "1", test2: "1", test3: "1", test4: "1" },
        { name: "3", test1: "1", test2: "1", test3: "1", test4: "1" },
        { name: "4", test1: "1", test2: "1", test3: "1", test4: "1" },
        { name: "5", test1: "1", test2: "1", test3: "1", test4: "1" },
        { name: "6", test1: "1", test2: "1", test3: "1", test4: "1" },
        { name: "7", test1: "1", test2: "1", test3: "1", test4: "1" },
        { name: "8", test1: "1", test2: "1", test3: "1", test4: "1" },
        { name: "9", test1: "1", test2: "1", test3: "1", test4: "1" },
        { name: "10", test1: "1", test2: "1", test3: "1", test4: "1" },
        { name: "11", test1: "1", test2: "1", test3: "1", test4: "1" },
        { name: "12", test1: "1", test2: "1", test3: "1", test4: "1" },
        { name: "13", test1: "1", test2: "1", test3: "1", test4: "1" },
        { name: "14", test1: "1", test2: "1", test3: "1", test4: "1" },
        { name: "15", test1: "1", test2: "1", test3: "1", test4: "1" },
        { name: "16", test1: "1", test2: "1", test3: "1", test4: "1" },
      ],
      pageSize: 10,
      currentPage: 1,
    };
  },
  computed: {
    showTableData() {
      return this.tableData.slice(
        (this.currentPage - 1) * this.pageSize,
        this.currentPage * this.pageSize
      );
    },
  },
  methods: {
    // 分页
    handleCurrentChange(val) {
      this.currentPage = val;
    },
    handleSizeChange(val) {
      this.pageSize = val;
      // 切换每页数量的时候一定要讲页码设置为1,不然会出错
      this.currentPage = 1;
    },
  },
};
</script>

1746521620738.png

2.后端分页

那就更没啥说的了,传参的时候把页码和每页数量传过去就好了。

5.隐藏表格纵向滚动条

有时候为了美观,会要求去隐藏一下右侧的滚动条。

这是原本页面,用的还是讲分页时候的页面。

1746521620738.png

我们用css的方式去隐藏一下右侧的滚动条,我们前面就说了表格分为三部分,其中横向滚动条是在bodyWrapper上的,不言而喻纵向滚动条也在这上面,换成类名就是el-table__body-wrapper

image.png

而滚动条是在el-table__body-wrapper的伪类上面的。

1746522114781.png

这个伪类指的是滚动条的整体(回头会出个帖专门讲滚动条样式),我们只需要修改这个类的样式就好了。

::v-deep .el-table {
  .el-table__body-wrapper {
    &::-webkit-scrollbar {
      // 整个滚动条
      width: 0px; // 纵向滚动条的宽度
    }
  }
}

1746522288603.png

这样看虽然滚动条没了,但是有一个空隙也很影响美观,所以还要修改。

这个空隙我暂时也讲不好原理,就直接给结果了。

::v-deep .el-table {
  .el-table__body-wrapper {
    &::-webkit-scrollbar {
      // 整个滚动条
      width: 0px; // 纵向滚动条的宽度
      background: red;
      background-color: purple;
    }
  }

  // 隐藏table gutter列和内容区右侧的空白
  th.gutter {
    display: none !important;
    width: 0 !important;
  }

  colgroup col[name="gutter"] {
    display: none;
    width: 0;
  }

  .el-table__body {
    width: 100% !important;
  }
}

效果如下:

1746580384928.png

6.表格添加单选框

我们知道el-table有选择框功能,但是那个选择框是复选框,如果我们只想要单选框该怎么办呢?

我们可以用排他思想去让复选框只可以选择一个,但是这样总归不够完美,毕竟还是复选框,所以我选择用插槽slot自己给表格加一个单选框。

<template>
  <div>
    <el-table
      border
      style="height: 100%"
      stripe
      :header-cell-style="{ textAlign: 'center' }"
      :cell-style="{ textAlign: 'center' }"
      :data="tableData"
    >
      <el-table-column label="选择" width="55">
        <template slot-scope="scope">
          <el-radio
            :label="scope.$index"
            v-model="selectRowVal"
            @change="handleSelectChange(scope.row)"
          >
          </el-radio>
        </template>
      </el-table-column>
      <el-table-column label="姓名" prop="name"></el-table-column>
    </el-table>
  </div>
</template>

<script>
export default {
  data() {
    return {
      // 表格数据
      tableData: [{ name: "月亮" }, { name: "yuliang" }],
      // 单选绑定的值,也就是那个label属性,一般用不到
      selectRowVal: "",
    };
  },
  methods: {
    // 点击单选,就可以对该条数据进行处理
    handleSelectChange(row) {
      console.log(row);
    },
  },
};
</script>

<style lang="scss" scoped>

// 隐藏单选框的label
::v-deep .el-table {
  .el-radio__label {
    display: none;
  }
}
</style>

有一个注意点,这个el-radio组件的label的属性绑定的一定要是不同的值,不然选中一个其他的就全部都选中了,因为el-radio组件的label的属性就相当于是别的组件的value属性。

还有就是el-radio组件会显示一个文字,就是下面这个:

1747299246096.png

我们肯定不想要这个东西,所以用css去给它隐藏掉。

7.表格选择项发生变化时@selection-change方法触发两次

这个情况我复现不出来,情况就是此时我勾选表格单元行的时候,勾选框勾选不上,打印了@selection-change方法以后发现这个事件调用了两次,第一次是正常的,第二次是一个空数组,就相当于第二次触发的时候什么都没有勾选,所以表格单元行勾选不上,原因是因为表格数据data赋值的时候在里面做分页处理了,就下面这种情况。

    <el-table
      ref="tableRef"
      :data="
        tableData.filter(
          (item, index) =>
            (currentPage - 1) * currentSize <= index &&
            index < currentPage * currentSize
        )
      "
      height="calc(100% - 32px)"
      stripe
      border
      :cell-style="{ textAlign: 'center' }"
      :header-cell-style="{ textAlign: 'center' }"
      @selection-change="selectionChange"
    ></el-table>

我把这个分页处理单独拉出来做一个计算属性以后这种情况就没有再出现了,以后还得是规范写代码。

8.前端分页后勾选表格,在切换页码的时候保持勾选状态

一般情况下,我们在切换分页以后再切换回来,原来的勾选状态就会消失,如果我们想保留勾选状态就需要用到两个属性,一个是el-table的属性row-key,另外一个是el-table-column的属性reserve-selection

row-key是行数据的唯一值key,类型为字符串的时候就表示为prop,比如id表示行数据的唯一值key,如果没有类似于id这样可以代表key的属性,类型也可以为一个函数,返回一个几个属性拼接起来的值表示唯一值。reserve-selection是在type=selection的时候才会生效,类型为Boolean,为true则会在数据更新之后保留之前选中的数据(需指定 row-key)。

<template>
  <div class="screen-view">
    <el-table
      ref="tableRef"
      :data="showTableData"
      height="calc(100% - 32px)"
      stripe
      border
      :cell-style="{ textAlign: 'center' }"
      :header-cell-style="{ textAlign: 'center' }"
      @selection-change="selectionChange"
      row-key="id"
    >
      <el-table-column type="selection" width="50px" :reserve-selection="true">
      </el-table-column>
      <el-table-column label="姓名" prop="name"></el-table-column>
      <el-table-column label="年龄" prop="age"></el-table-column>
      <el-table-column label="岗位" prop="job"></el-table-column>
    </el-table>
    <el-pagination
      style="text-align: right"
      @size-change="handleSizeChange"
      @current-change="handleCurrentChange"
      :current-page="currentPage"
      :page-sizes="[2, 4, 6, 8]"
      :page-size="currentSize"
      layout="total,sizes, prev, pager, next, jumper"
      :total="total"
    >
    </el-pagination>
  </div>
</template>

<script>
export default {
  data() {
    return {
      // 表格数据
      tableData: [
        { id: "1", name: "123", age: 18, job: "前端工程师" },
        { id: "2", name: "123", age: 18, job: "前端工程师" },
        { id: "3", name: "123", age: 18, job: "前端工程师" },
        { id: "4", name: "123", age: 18, job: "前端工程师" },
        { id: "5", name: "123", age: 18, job: "前端工程师" },
        { id: "6", name: "123", age: 18, job: "前端工程师" },
        { id: "7", name: "123", age: 18, job: "前端工程师" },
      ],
      // 选择的表格数据
      selectionList: [],
      // 分页相关属性
      currentPage: 1,
      currentSize: 2,
      total: 0,
    };
  },
  computed: {
    showTableData() {
      return this.tableData.filter(
        (item, index) =>
          (this.currentPage - 1) * this.currentSize <= index &&
          index < this.currentPage * this.currentSize
      );
    },
  },
  created() {
    this.total = this.tableData.length;
  },
  methods: {
    // 表格单元行选择
    selectionChange(row) {
      this.selectionList = row;
      console.log(row);
    },
    // 切换页码
    handleSizeChange(val) {
      this.currentPage = 1;
      this.currentSize = val;
    },
    handleCurrentChange(val) {
      this.currentPage = val;
    },
  },
};
</script>

9.单元格合并的小巧思1

情况是这样,刚开始做表格的时候一般的情况下是下面这个样式。

image.png

但是现场要求,让我做成下面这个样式。

image.png

这一点应该怎么做呢,我们可以看到表格的类型列从第五行开始就从一个单元格分成左右两个单元格了,然后左边的单元格还做了一个合并,一个单元格分成两个单元格很好做,我们直接用插槽在单元格里面写两个div盒子就好了,但是这样的话,左边的单元格就不是那么好合并了。

所以我有了下面这个构思:

既然一个单元格分成两个单元格以后左边的单元格不好合并,那我不如让类型有两列,那就是有两个单元格,然后上面四行的两个类型列的单元格合并成一个单元格,然后第一个类型列的后面四行的的单元格再合并下就好了,但是表头是没法合并的,所以就会有两个类型表头出来,这样展示就不美观了,所以我们可以搞一个二级表头出来,就像下面这样。

image.png

然后我们把前四行的两个单元格合并成一个,后四行的左边单元格合并一下。就变成了下面这样。

image.png

这样是不是就基本满足了现场的需求,只要把E类给改成核心区域就好了,这一点我们就可以使用插槽去做个判断,如果是前四行的数据,就还是原来的样子,如果其他的的就直接改成核心区域就好了。然后再把二级表头给隐藏一下,就完美实现了现场的效果。

完整代码:

<template>
  <div class="screen-view">
    <el-table :data="tableData" stripe border height="400" :cell-style="{ textAlign: 'center' }"
      :header-cell-style="{ textAlign: 'center' }" :span-method="objectSpanMethodHandle">
      <el-table-column type="index" label="序号"></el-table-column>
      <el-table-column label="类型" min-width="200px" show-overflow-tooltip>
        <!-- 类型二级表头左边 -->
        <!-- 左边需要处理下,因为左边前四行还是正常展示,后四行就得改成固定文字核心区域 -->
        <el-table-column prop="type" label="类型" min-width="200px" show-overflow-tooltip>
          <template #default="{ row, $index }">
            <!-- 如果是前四行就还是原来的值,否则就改成核心区域 -->
            {{ $index <= 3 ? row.type : '核心区域' }} </template>
        </el-table-column>
        <!-- 类型二级表头左边右边 -->
        <!-- 右边不需要处理,前四行都不展示了,后四行正常展示就行了 -->
        <el-table-column prop="type" label="类型" min-width="200px" show-overflow-tooltip></el-table-column>
      </el-table-column>
      <el-table-column prop="start" label="初始值" min-width="100px" show-overflow-tooltip></el-table-column>
      <el-table-column prop="end" label="最终值" min-width="100px" show-overflow-tooltip></el-table-column>
    </el-table>
  </div>
</template>

<script>
export default {
  data() {
    return {
      // 表格数据
      tableData: [
        { type: "A类", start: "10", end: "100" },
        { type: "B类", start: "20", end: "200" },
        { type: "C类", start: "30", end: "300" },
        { type: "D类", start: "40", end: "400" },
        { type: "E类", start: "50", end: "500" },
        { type: "F类", start: "60", end: "600" },
        { type: "G类", start: "70", end: "700" },
        { type: "H类", start: "80", end: "800" },
      ],
    };
  },
  methods: {
    // 合并方法
    objectSpanMethodHandle({ row, column, rowIndex, columnIndex }) {
      // 前四行且第二列 要展示的单元格
      if (rowIndex <= 3 && columnIndex === 1) {
        return {
          rowspan: 1,  // 纵向还是一个单元格
          colspan: 2,  // 横向合并两个单元格
        };
      }
      // 前四行第三列 因为被第二列合并了所以这里要给它去掉
      if (rowIndex <= 3 && columnIndex === 2) {
        return {
          rowspan: 0,
          colspan: 0,
        };
      }
      // 第五行第二列
      if ((rowIndex === 4 && columnIndex === 1)) {
        return {
          rowspan: 4,  // 纵向合并四个单元格
          colspan: 1,  // 横向还是一个
        };
      }
      // 第五行后面行的第一列 因为被第五行给合并了 所以这里也要去掉
      if (rowIndex > 4 && columnIndex === 1) {
        return {
          rowspan: 0,
          colspan: 0,
        };
      }
    },
  }
};
</script>

<style lang="scss" scoped>
.screen-view {
  height: 100%;
  padding: 100px;
}

// 隐藏二级表头
::v-deep .el-table .el-table__header-wrapper .is-group tr:nth-child(2) {
  display: none;
}
</style>

当然要根据具体情况来看,因为我这个表格的数据是固定返回这么几条,所以我合并方法就直接写的,如果你们返回数据量不固定,还是得遍历数据进行处理,我这个只是提供一种思路,遍历表格数据进行单元格合并的方法,我其他帖子也写过可以自己去看看。