最终实现效果
在这里插入图片描述

1、业务描述
在开发过程中,一个表格需要无分页展示出几万条的数据。并且表格有几十甚至一百多列。
2、现象及问题原因
正常使用el-table渲染表格页面直接卡死。
一次性渲染了几万条,几十列,造成大量DOM一次性渲染,直接造成至使页面卡死。
曾尝试使用组件unmy-ui解决卡顿问题,但效果不显著…
3、解决方案
采用数据结合盒子滚动实现数据动态滚动效果。
思路:动态替换可视区域的数据。
我所写的案例是默认展示十条,接下来按十条描述。
主体内容显示部分:页面默认进入显示的是第一个十条,也就是索引的[0,9]。当盒子滚动的时候滚动了一行默认显[1,10],两行[2,11]…以此类推。
这个位置永远都是只展示十条。在这里插入图片描述
滚动盒子:计算出来当前所有数据的高度(为了方便计算行高默认相同,案例中行高45px),以便于撑起来盒子高度,显示滚动条。

ps:目前存在一个问题,鼠标必须在滚动条的盒子上移动才会有效果。这个有待研究…

画了一图展示下层叠关系
在这里插入图片描述
如果使用触底懒加载方式,也会因为DOM加载过多造成页面卡顿。
4、代码部分
代码很全也很简单,运行一下就能看明白。滚动向上滚动向下都能根据位置自动显示对相应数据。

<template>
  <div class="box">
     <!-- false-box这是一个用来显示滚动条的方法 -->
    <div class="false-box"> 
      <div class="scroll-box" :style="{'height': scollBoxHeight + 'px'}">
       <!-- scroll-box是用来撑起盒子的方法 -->
      </div>
    </div>
    <div class="table-box">
      <el-table
        :data="tableData"
        style="width: 100%">
        <el-table-column
          prop="date"
          label="日期"
          width="180">
        </el-table-column>
        <el-table-column
          prop="name"
          label="姓名"
          width="180">
        </el-table-column>
        <el-table-column
          prop="address"
          label="地址">
        </el-table-column>
      </el-table>
    </div>
  </div>
</template>
<script>
export default {
  data() {
    return {
      allData:[],
      tableData: [],
      elTableHeight: '',  //el-table的高度
      theadHeight: '',  //表头的高度
      contentHeight: 0, //主要内容高度
      showRowCount: 0, //一共能显示多少行 
      falseBox: 0,  //后边假盒子的高度
      scollBoxHeight: 0, //假滚动条的高度
      scrollTopRowCount: 0, //一共向上滚动了多少行
    }
  },
  mounted() {
    let that = this;
    // 模拟一万条假数据
    for(let i = 0; i < 10000; i++) {
      this.allData.push({
        date: i+ 1,
        name: '王小虎',
        address: '上海市普陀区金沙江路 1518 弄'
      })
    }
    this.scollBoxHeight = 45 * this.allData.length + 45; //多加一行,要不然滚动到底差一行
    this.$nextTick( () => {
      this.elTableHeight = document.querySelector('.table-box .el-table').offsetHeight;
      this.theadHeight = document.querySelector('.table-box .el-table__header-wrapper').offsetHeight;
      this.contentHeight = this.elTableHeight - this.theadHeight;
      this.showRowCount = Math.floor(this.contentHeight / 45);
      // 获取默认显示的前 <showRowCount> 条
      this.tableData = JSON.parse(JSON.stringify(this.allData)).splice(0,this.showRowCount);
    })
    this.falseBox = document.querySelector('.false-box');
    this.falseBox.addEventListener('scroll', function(e) {
      that.scrollTopRowCount =  Math.ceil(e.target.scrollTop / 45);
      // 获取从索引<scrollTopRowCount> 开始 <showRowCount> 条
      that.tableData = JSON.parse(JSON.stringify(that.allData)).splice(that.scrollTopRowCount, that.showRowCount);
    });
  },
}
</script>
<style lang="scss" scoped>
.box {
  width: 1000px;
  height: 500px;
  overflow: hidden;
  position: relative;
  .false-box {
    width: 100%;
    height: 100%;
    position: absolute;
    top: 0%;
    left: 0%;
    overflow: auto;
    .scroll-box {
      width: 100%;
      height: 1000px;
      position: absolute;
    top: 0%;
    left: 0%;
    }
  }
  .table-box {
    width: calc(100% - 20px);
    height: 100%;
    position: absolute;
    top: 0%;
    left: 0%;
  }
}
::v-deep .el-table {
  width: 100%;
  height: 100%;
  .el-table__row {
    height: 45px;
    td {
      padding: 0px 
    }
  }
}
</style>
Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐