实现虚拟列表技术

157 阅读1分钟

实现虚拟列表技术

实现虚拟列表技术的关键在于渲染可见区域内的数据,而非所有数据。这可以通过计算可见区域的位置和大小,然后根据数据项的高度和总数量,计算出需要渲染的数据项的范围来实现。

<template>
  <div class="container" ref="container" @scroll="handleScroll">
    <div :style="{ height: totalHeight + 'px' }">
      <div v-for="(item, index) in visibleData" :key="index" :style="{ height: itemHeight + 'px' }">
        {{ item }}
      </div>
    </div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      data: [], // 数据列表
      itemHeight: 50, // 数据项的高度
      containerHeight: 0, // 可见区域的高度
      scrollTop: 0, // 滚动条的位置
      visibleStartIndex: 0, // 可见区域内的第一个数据项的索引
      visibleEndIndex: 0, // 可见区域内的最后一个数据项的索引
      buffer: 5 // 缓冲区大小,即在可见区域的上下各预留多少个数据项
    }
  },
  computed: {
    totalHeight() {
      return this.data.length * this.itemHeight
    },
    visibleData() {
      return this.data.slice(this.visibleStartIndex, this.visibleEndIndex + 1)
    }
  },
  methods: {
    handleScroll() {
      this.scrollTop = this.$refs.container.scrollTop
      this.containerHeight = this.$refs.container.clientHeight
      this.visibleStartIndex = Math.floor(this.scrollTop / this.itemHeight) - this.buffer
      this.visibleEndIndex = Math.ceil((this.scrollTop + this.containerHeight) / this.itemHeight) + this.buffer - 1
      if (this.visibleStartIndex < 0) {
        this.visibleStartIndex = 0
      }
      if (this.visibleEndIndex >= this.data.length) {
        this.visibleEndIndex = this.data.length - 1
      }
    }
  },
  mounted() {
    // 生成 10000 条数据
    for (let i = 0; i < 10000; i++) {
      this.data.push(`Item ${i}`)
    }
  }
}
</script>

首先通过计算总高度和可见区域的高度来确定可见区域内的数据项数量。然后根据滚动条的位置和缓冲区大小来计算出可见区域内的第一个和最后一个数据项的索引,最后使用Array.slice()方法来获取可见区域内的数据。这是一个简单的例子,具体根据项目实际有所改变。