让我优化一个几千列的多级表头表格,我麻了

619 阅读2分钟

事情是这样的,我年前写了一个多级表头的表格张这个样子

image.png 但是甲方的电脑是那种内存特别拉胯的台式机,在打开页面的时候频频卡死,浏览器崩溃,我的16g内存电脑也偶尔复现。。。

image.png 好吧,所以最近领导让我优化,我提方案是搞一个数据分页(不允),然后横竖颠倒(驳回),这两种方案都不允许,非得一次看几千列的数据,mdzz! 没办法,搞个懒加载吧。 也简单,代码如下

<template>
  <el-table
    ref="tableRef"
    v-loading="loading"
    height="600px"
    @scroll="handleScroll"
    :data="newTableData"
  >
  
    <el-table-column
      v-for="el in visibleColumnGroups"
      :key="el.headerSort"
      :label="el.headerName"
      align="center"
      min-width="230"
    >
      <el-table-column
        v-for="i in el.childList"
        :key="i.headerSort"
        align="center"
        min-width="300"
        :label="i.headerName"
      >
        <el-table-column
          v-for="c in i.childList"
          :key="c.headerSort"
          align="center"
          min-width="120"
          show-overflow-tooltip
          :label="c.headerName"
          :prop="c.headerSort.toString()"
        >
  
        </el-table-column>
      </el-table-column>
    </el-table-column>
  </el-table>
</template>
<script>

export default {
  data() {
    return {
      totalWidth: 100,
      startIndex: 0,   // 开始位置
      initMount: 5,   // 默认展示起始数量
      isScrolling: false,  // 滚动状态
      COLUMN_GROUP_WIDTH: 600, // 滚动距离更新
      visibleColumnGroups: [{}],  // 懒加载展示数据
    };
  },

  props: {
    tableColumn: {
      type: Array,
      default: () => {
        return [];
      },
    },
    loading: {
      type: Boolean,
      default: false,
    },
  
    tableData: {
      type: Array,
      default: () => {
        return [];
      },
    },
  
  },
  mounted() {
    this.$nextTick(() => {
      const bodyWrapper = this.$refs.tableRef.$el.querySelector(
        ".el-table__body-wrapper",
      );
      if (bodyWrapper) {
        bodyWrapper.addEventListener("scroll", this.handleScroll);
      }
    });
  },
  beforeDestroy() {
    // 移除滚动监听
    const bodyWrapper = this.$refs.tableRef.$el.querySelector(
      ".el-table__body-wrapper",
    );
    if (bodyWrapper) {
      bodyWrapper.removeEventListener("scroll", this.handleScroll);
    }
  },
  computed: {
    newTableData() {
      const headerSorts = ["00"];
      this.tableColumn.map((column) => {
        column.childList.map((child) => {
          if (child.childList) {
            child.childList.forEach((el) => {
              headerSorts.push(el.headerSort);
            });
          } else {
            headerSorts.push(child.headerSort);
          }
        });
      });
      const newtable = [];
      this.tableData.map((row) => {
        const obj = {};
        headerSorts.map((code) => {
          // 查找 reportList 项的对应 headerSort
          const item = row.find((item) => item.headerSort === code);
          obj[code] = item;
        });
        newtable.push(obj);
      });
      if (this.tableData[0]) {
        this.totalWidth = this.tableData[0].length * this.COLUMN_GROUP_WIDTH;
      }
      this.calculateTableHeight();
      this.loadColumns(0);
      return newtable;
    },
  },
  methods: {
    changeChecked() {
      this.$emit("changeChecked");
    },
    handleClick(type, data) {
      this.$emit("emitMethod", { type, data });
    },
    exportData() {
      const data = this.$refs.tableRef.data;
      const newtable = [];
      data.map((row) => {
        const item = [];
        for (const key in row) {
          item.push(row[key]);
        }
        newtable.push(item);
      });
      return newtable;
    },
    /**
     * @Description: 加载可见列组
     * @Author: zhangyantao
     * @Date: 2025-03-05 16:45:11
     * @LastEditTime:
     * @LastEditors: zhangyantao
     * @param {*} endIndex
     */
    loadColumns(endIndex) {
      this.visibleColumnGroups = this.tableColumn.slice(
        0, // 预加载前5组
        this.initMount + endIndex,
      );
      this.$nextTick(() => {
        this.$refs.tableRef.doLayout();
      });
    },

    /**
     * @Description: 处理滚动事件
     * @Author: zhangyantao
     * @Date: 2025-03-05 16:44:58
     * @LastEditTime:
     * @LastEditors: zhangyantao
     * @param {*} e
     */
    handleScroll(e) {
      if (this.isScrolling) return;
      this.isScrolling = true;
      requestAnimationFrame(() => {
        const scrollLeft = e.target.scrollLeft;
        const startIndex = Math.floor(scrollLeft / this.COLUMN_GROUP_WIDTH);
        if (this.startIndex < startIndex) {
          this.loadColumns(startIndex);
          this.startIndex = startIndex;
          console.log(startIndex, this.startIndex);
        }
        this.isScrolling = false;
      });
    },
  },
};
</script>

如代码所示,当table横向滚动,超过设定值时,向懒加载表头数据赛一条数据,更新表格

 this.$nextTick(() => {
        this.$refs.tableRef.doLayout();
      });

处理表格错乱问题,目前先这样处理,有大佬有其他方法,可以评论区告知一二,在此谢过。