前端表格数据量太大,导致页面崩溃(最优解决办法做滚动加载)

lxf2023-05-18 01:43:24

需求:

需要在页面上加载有数千行数据的表格;

1.正常加载 (数据量大的话,页面会加载过久,页面卡顿会导致浏览器崩溃)

    this.tableData = 数据;

前端表格数据量太大,导致页面崩溃(最优解决办法做滚动加载)

2.懒加载

优点:页面每次进入时加载速度都很快。

缺点:页面滚动到所有数据都加载完后,如果数据量大,页面也会卡顿

<template>
    <el-table v-loading="tableLoading" ref="table" :data="tableData" height="700" 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>
</template
<script>
export default {
 data() {
  return {
    tableData: [], //用来存放页面显示的数据
    allTableData: [], //用来存放所有数据
    tableLoading: false,//页面加载
  }
 },
 created() {
    this.init()
 },
 mounted(){
     //给表格注册滚动事件
     this.$nextTick(()=>{
       const tableWrap = document.querySelector(".el-table__body-wrapper");
       tableWrap.addEventListener("scroll",()=>{
         this.loadMore()
       })
     })
 },
 methods: {
    //数据初始化事件
    init() {
        this.tableLoading = true;
        this.allTableData = 10000条数据;
        this.tableData = this.allTableData.slice(0, 20);
        //因页面高度只能显示13行内容,所以第一次加载20条
        this.tableLoading = false;
    },
    //页面滚动事件
    loadMore() {
        // this.$refs.table.bodyWrapeer.scrollHeight 滚动条总高度
        // this.$refs.table.bodyWrapeer.scrollTop 滚动条距离顶部距离
        // this.$refs.table.bodyWrapeer.clientHeight 盒子可视区高度
        const scrollValue = this.$refs.table.bodyWrapeer.scrollHeight -
        this.$refs.table.bodyWrapeer.scrollTop -
        this.$refs.table.bodyWrapeer.clientHeight;

        //如果距离底部小于等于200,并且页面展示的内容数组长度与总内容数据长度不一致,则可以往显示内容中追加
        if (scrollValue <= 200 && this.tableData.length !== this.allTableData.length) {
        this.tableLoading = true;
        let tableData = []
        //总内容多出显示内容不止20行,就追加20行
        if (this.allTableData.length - this.tableData.length > 20) {
        tableData = this.tableData.concat(this.allTableData.slice(this.tableData.length, this.tableData.length+20))
        } else { //少于20行,就把剩余的所有内容追加进去
        tableData = this.tableData.concat(this.allTableData.slice(this.tableData.length))
        }
        setTimeout(() => {
        this.tableData = tableData;
        this.tableLoading = false;
        })
      }
    }
  }
}
</script>
<style>
</style>

3.滚动加载,虚拟列表

<template>
    <el-table v-loading="tableLoading" ref="table" :data="tableData" height="700" 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>
</template
<script>
export default {
 data() {
  return {
    tableData: [], //用来存放页面显示的数据
    allTableData: [], //用来存放所有数据
    tableLoading: false,//页面加载
    startNum:0, //起始坐标
    endNum:0, //结束坐标
  }
 },
 created() {
    this.init()
 },
 mounted(){
     //给表格注册滚动事件
     this.$nextTick(()=>{
       const tableWrap = document.querySelector(".el-table__body-wrapper");
       tableWrap.addEventListener("scroll",()=>{
         this.loadMore()
       })
     })
 },
 methods: {
    //数据初始化事件
    init() {
        this.tableLoading = true;
        this.allTableData = 10000条数据;
        this.endNum = this.allTableData.length >20 ? 20 : this.allTableData.length;
        this.tableData = this.allTableData.slice(0, this.endNum);
        this.tableLoading = false;
    },
    //页面滚动事件
    loadMore() {
        // this.$refs.table.bodyWrapeer.scrollHeight 滚动条总高度
        // this.$refs.table.bodyWrapeer.scrollTop 滚动条距离顶部距离
        // this.$refs.table.bodyWrapeer.clientHeight 盒子可视区高度
        const scrollValue = this.$refs.table.bodyWrapeer.scrollHeight -
        this.$refs.table.bodyWrapeer.scrollTop -
        this.$refs.table.bodyWrapeer.clientHeight;

        //如果距离底部小于等于200,并且页面展示的内容数组长度与总内容数据长度不一致,则可以往显示内容中追加
        if (scrollValue <= 200 && this.endNum !== this.allTableData.length) {
            this.tableLoading = true;
            let tableData = []
            //总内容多出显示内容不止20行,就追加20行
            if (this.allTableData.length - this.endNum > 20) {
                tableData = this.tableData.concat(this.allTableData.slice(this.endNum, this.endNum+20));
                this.endNum = this.endNum+20;
            } else { //少于20行,就把剩余的所有内容追加进去
                tableData = this.tableData.concat(this.allTableData.slice(this.endNum));
                this.endNum = this.allTableData.length;
            }
            
            if(tableData.length > 40) {
                //只要大于40行,就删除最上面的20行
                tableData.splice(0,20);
                //滚动条恢复到未到顶部的状态
                this.$refs.table.bodyWrapper.scrollTop = this.$refs.table.bodyWrapper.scrollTop - 800;
                //拿到现在最顶部的节点坐标
                this.startNum = this.endNum - tableData.length;
            }
            
            setTimeout(() => {
            this.tableData = tableData;
            this.tableLoading = false;
            },300)
          }
       } else if (this.$refs.table.bodyWrapper.scrollTop <= 200 && this.startNum !== 0) {
       //如果滚动条距离顶部小于等于200,并且最顶部的节点坐标并不为0,则往上加载
            this.tableLoading = true;
            let tableData = []
            //顶部剩余不止20行
            if (this.startNum > 20) {
                tableData = this.tableData.concat(this.allTableData.slice(this.startNum -20, this.startNum));
                this.startNum = this.startNum - 20;
            } else { //少于20行,就把剩余的所有内容追加进去
                tableData = this.tableData.concat(this.allTableData.slice(0this.startNum));
                this.startNum = 0;
            }
            
            if(tableData.length > 40) {
                //只要大于40行,就删除最上面的下面20行
                tableData.splice(40,20);
                //滚动条恢复到未到顶部的状态
                this.$refs.table.bodyWrapper.scrollTop = this.$refs.table.bodyWrapper.scrollTop + 800;
                //拿到现在最顶部的节点坐标
                this.endNum = this.startNum + 40;
            }
            
            setTimeout(() => {
            this.tableData = tableData;
            this.tableLoading = false;
            },300)
          }
       }
    }
}
</script>
<style>
</style>
本网站是一个以CSS、JavaScript、Vue、HTML为核心的前端开发技术网站。我们致力于为广大前端开发者提供专业、全面、实用的前端开发知识和技术支持。 在本网站中,您可以学习到最新的前端开发技术,了解前端开发的最新趋势和最佳实践。我们提供丰富的教程和案例,让您可以快速掌握前端开发的核心技术和流程。 本网站还提供一系列实用的工具和插件,帮助您更加高效地进行前端开发工作。我们提供的工具和插件都经过精心设计和优化,可以帮助您节省时间和精力,提升开发效率。 除此之外,本网站还拥有一个活跃的社区,您可以在社区中与其他前端开发者交流技术、分享经验、解决问题。我们相信,社区的力量可以帮助您更好地成长和进步。 在本网站中,您可以找到您需要的一切前端开发资源,让您成为一名更加优秀的前端开发者。欢迎您加入我们的大家庭,一起探索前端开发的无限可能!