el-table加载大数据导致页面崩溃的解决方法

180 阅读1分钟
  • 懒加载,首次只加载规定数量的数据,避免一次性加载过多数据导致页面崩溃
  • 利用监听表格滚动事件,当滚动表格底部时触发数据拼接然后重新渲染
<template>
  <el-table ref="table" height="400px" :data="table.tableDataList" :key="key" :loading="dataListLoading">
    <el-table-column type="index" align="center" label="序号" width="60">
    </el-table-column>
    <el-table-column v-for="(value, index) in table.tableHeader" :prop="String(index)" :label="value" :key="index">
    </el-table-column>
  </el-table>
</template>

<script>
export default {
  data() {
    return {
      dom: null,
      pageData: {
        dataStep: 500, //每次加载数据条数
        dataTotal: 0,// 数据总行数
        dataNum: 0,// 当前加载了多少条数据
        dataNumPre: 0// 上一次加载的数据条数
      },
      table: {
        tableHeader: [],
        tableDataList: []
      },
      allDataTable: {
        tableHeader: [],
        tableDataList: []
      },
      showNum: 0,
      key: 0,
      dataListLoading: true
    }
  },
  created() {
    // 模拟大数据
    let dataArr = []
    for (let index = 0; index < 20; index++) {
      this.allDataTable.tableHeader.push('head-' + index);
      dataArr.push('data-' + index);
    }
    for (let index = 0; index < 5000; index++) {
      this.allDataTable.tableDataList.push(dataArr);
    }
    this.table.tableHeader = this.allDataTable.tableHeader;
  },
  mounted() {
    this.dom = this.$refs.table.bodyWrapper
    this.getMoreData();
  },
  methods: {
    bindTbale() {
      // 获取需要绑定的table
      this.dom = this.$refs.table.bodyWrapper
      let domFunc = () => {
        let scrollTop = this.dom.scrollTop
        // 变量windowHeight是可视区的高度
        let windowHeight = this.dom.clientHeight || this.dom.clientHeight
        // 变量scrollHeight是滚动条的总高度
        let scrollHeight = this.dom.scrollHeight || this.dom.scrollHeight

        // 控制滚动触发加载条件
        if (scrollTop + windowHeight + 2 > scrollHeight) {
          // 获取到的不是全部数据 当滚动到底部 继续获取新的数据
          this.getMoreData()
          console.log('scrollTop', scrollTop + 'windowHeight', windowHeight + 'scrollHeight', scrollHeight)
        }
      }
      this.dom.removeEventListener("scroll", domFunc)
      this.dom.addEventListener('scroll', domFunc)
    },
    getMoreData() {
      if (this.showNum % 2 == 1) {
        console.warn('频繁刷新');
        return;
      }
      this.dataListLoading = true;
      this.showNum++;

      if (this.pageData.dataNum == this.pageData.dataTotal) {
        this.dataListLoading = false;
        return;
      }

      this.pageData.dataNumPre = this.pageData.dataNum;
      this.pageData.dataNum = ((this.pageData.dataNum + this.pageData.dataStep) <= this.pageData.dataTotal)
        ? this.pageData.dataNum + this.pageData.dataStep
        : this.pageData.dataTotal;

      this.table.tableDataList = this.table.tableDataList.concat(this.allDataTable.tableDataList.slice(this.pageData.dataNumPre, this.pageData.dataNum));

      this.key++;

      setTimeout(() => {
        this.bindTbale()
        this.showNum++;
        this.dataListLoading = false;
        this.dom.scrollTop = this.dom.scrollHeight * (this.pageData.dataNumPre / this.pageData.dataNum);
      }, 3000)


    },
    resetPageData() {
      this.showNum = 0;
      this.pageData = {
        dataStep: 500,
        dataTotal: 0,
        dataNum: 0,
        dataNumPre: 0
      }
    }
  }
}
</script>

<style></style>