美文网首页
使用虚拟列表解决长列表卡顿

使用虚拟列表解决长列表卡顿

作者: Yinzhishan | 来源:发表于2022-08-23 14:09 被阅读0次

    理论

    当我们有大量数据需要渲染时,会照成页面的卡顿,这是由于页面的dom太多照成的,我我们可以使用虚拟列表来优化显示。
    虚拟列表的核心实现有两部分,

    1. 可滚动区域:假设有 1000 条数据,每个列表项的高度是 30,那么可滚动的区域的高度就是 1000 * 30。当用户改变列表的滚动条的当前滚动值的时候,会造成可见区域的内容的变更。
    2. 可见区域:比如列表的高度是 300,右侧有纵向滚动条可以滚动,那么视觉可见的区域就是可见区域。

    实现虚拟列表就是处理滚动条滚动后的可见区域的变更,其中具体步骤如下:
    计算当前可见区域起始数据的 startIndex
    计算当前可见区域结束数据的 endIndex
    计算当前可见区域的数据,并渲染到页面中
    计算 startIndex 对应的数据在整个列表中的偏移位置 startOffset,并设置到列表上;


    微信图片_20220823111909.jpg

    使用vue的一个简单实现

    <!-- 虚拟列表 -->
    
    <template>
      <div class="list-view" @scroll="handleScroll">
        <div
          class="list-view-phantom"
          :style="{
            height: contentHeight,
          }"
        ></div>
        <div ref="content" class="list-view-content">
          <div
            class="list-view-item"
            :style="{
              height: itemHeight + 'px',
            }"
            v-for="item in visibleData"
          >
            {{ item }}
          </div>
        </div>
      </div>
    </template>
    
    <script>
    export default {
      name: "HelloWorld",
    
      props: {
        data: {
          type: Array,
          required: true,
        },
    
        itemHeight: {
          type: Number,
          default: 30,
        },
      },
    
      computed: {
        contentHeight() {
          return this.data.length * this.itemHeight + "px";
        },
      },
    
      mounted() {
        this.updateVisibleData();
      },
    
      data() {
        return {
          visibleData: [],
        };
      },
    
      methods: {
        updateVisibleData(scrollTop) {
          scrollTop = scrollTop || 0;
          const visibleCount = Math.ceil(this.$el.clientHeight / this.itemHeight);
          const start = Math.floor(scrollTop / this.itemHeight);
          const end = start + visibleCount;
          this.visibleData = this.data.slice(start, end);
          this.$refs.content.style.webkitTransform = `translate3d(0, ${
            start * this.itemHeight
          }px, 0)`;
        },
    
        handleScroll() {
          const scrollTop = this.$el.scrollTop;
          this.updateVisibleData(scrollTop);
        },
      },
    };
    </script>
    <style>
    .list-view {
      height: 400px;
      overflow: auto;
      position: relative;
      border: 1px solid #aaa;
    }
    
    .list-view-phantom {
      position: absolute;
      left: 0;
      top: 0;
      right: 0;
      z-index: -1;
    }
    
    .list-view-content {
      left: 0;
      right: 0;
      top: 0;
      position: absolute;
    }
    
    .list-view-item {
      padding: 5px;
      color: #666;
      line-height: 30px;
      box-sizing: border-box;
    }
    </style>
    
    

    相关文章

      网友评论

          本文标题:使用虚拟列表解决长列表卡顿

          本文链接:https://www.haomeiwen.com/subject/wefggrtx.html