Element表格长列表渲染太慢太卡如何优化?(缩短加载时间)

解决思路

利用列表懒加载(虚拟列表)
我们一次拿到所有数据但是只渲染10条数据,只要把页面填满就行.等用户拉动滚动条到达底部时我们就填加渲染数据30条.
因为我们多个页面需要用到懒加载,所以我们提取成公共方法mixin
代码注释很详细,具体看注释即可

实操:

封装minxin

在这里插入图片描述
因为vue是单页面应用所以一定要记得销毁滚动事件监听

export default {
    data: function () {
        return {
            times: null,
            dom: '',
            loading: false,
            oldTop: 0,
            tableData1: [],
        }
    },
    mounted() {
        // 获取需要绑定的table
        // this.dom = this.$refs.multipleTable.bodyWrapper
        this.dom = document.getElementsByClassName('el-main')[0]
        this.dom.addEventListener('scroll', this.listLoading)
    },
    methods: {
        // 懒加载
        listLoading() {
            // 表格滚动条滚动的距离
            let scrollTop = this.dom.scrollTop
            // 变量windowHeight是可视区的⾼度
            let windowHeight = this.dom.clientHeight
            // 变量scrollHeight是滚动条的总⾼度
            let scrollHeight = this.dom.scrollHeight
            // 记住上次位置
            this.oldTop = scrollTop
            // 滚动到到底并且数据全部加载完毕就提示到最底部了,直接return出去
            if (scrollTop + windowHeight > scrollHeight - 2 && this.tableData1.length == this.tableData.length) {
                if (this.times) {
                    this.loading = false
                    return
                }
                this.times = setTimeout(() => {
                    this.$message({
                        message: '已经到最底部了~',
                        type: 'success',
                        duration: 1500
                    });
                    this.times = null;
                }, 1500);
                return
            }
            console.log(scrollTop, windowHeight, scrollHeight);
            if (scrollTop + windowHeight > scrollHeight - 500) {   // 这里就是滚动条快滚动到底部的时候
                // 获取到的不是全部数据当滚动快到底部继续获取新的数据
                console.log('触发添加数据');
                // 这里记住我们要把表格渲染的数据和获取到的全部数据分开, 等滑动到底部时我们在取10或者20条添加到渲染数据上
                this.loading = true  // 开启loading效果防止渲染速度慢用户乱点,导致页面崩溃
                if (this.tableData1.length + 30 > this.tableData.length) {
                    // 如果全部数据和渲染数据选差没有三十条那么就全部渲染上去
                    this.tableData1 = this.tableData
                } else {
                    let id = this.tableData1.length
                    // 这里取20条,渲染上去 拿多少数据循环多少次就行
                    for (let index = id - 1; index <= id + 29; index++) {  // 没有用forEach 因为场景不同这里用 forEach 效率会低 
                        this.tableData1.push(this.tableData[index])
                    }
                    if (this.oldTop) {
                        // 当指令检测到DOM已经渲染好(nextTick下一个节点加载完毕),立即恢复之前记录的scrollTop。不等dom渲染完scrollTop会不准
                        this.$nextTick(() => {
                            this.dom.scrollTop = this.oldTop
                        })
                    }
                    this.oldTop = scrollTop
                }
                this.loading = false
            }
        }
    },
    //因为vue是单页面应用所以一定要记得销毁事件监听
    destroyed() {
        this.dom.removeEventListener("scroll", this.listLoading);
    },
}
页面使用
import mixin from '../../utils/mixin'
export default {
  mixins: [mixin],
  //接口调用
   this.$apiFun
        .firstList({
          limit: this.formInline.limit,
          page: this.formInline.page,
        })
        .then((res) => {
        //把上次记录清空再push
          this.tableData1 = [];
          if (res.code == 0) {
            this.tableData = res.data;
            this.formInline.total = res.count;
            //渲染条数小于100就让他一次全渲染出来,否则就分批渲染
            if (this.formInline.limit > 100) {
              for (let index = 0; index < 10; index++) {
                this.tableData1.push(this.tableData[index])
              }
            } else {
              this.tableData1 = this.tableData;
            }
            this.loading = false;
            // 切换展示条数的时候让滚动条移动一点就可以触发添加数据操作
            this.dom.scrollTop = this.oldTop - 1
            //因为这里要对数据做处理浪费时间,上面我们直接取十条先渲染,这里更改页面也会发证改变
            this.tableData.forEach((item) => {
              if (item.sentence) {
                item.sentence1 =
                  item.sentence.slice(0, item.offset) +
                  `<span style="background:#ffd8d6;border-bottom:1px solid #ff3b30;color:#000">${item.sentence.slice(
                    item.offset,
                    item.offset + item.errorWord.length
                  )}</span>` +
                  item.sentence.slice(
                    item.offset + item.errorWord.length,
                    item.offset.length
                  );
              }
          }
        })
        .catch((data) => {
          console.log(data);
        });
}


效果

初次渲染,脚本执行由2200毫秒优化到75毫秒左右,渲染由600多毫秒优化到19多毫秒
在这里插入图片描述
优化后
在这里插入图片描述

  • 0
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

前端老实人

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值