当前位置:首页 > VUE

vue虚拟滚动实现

2026-01-16 18:33:08VUE

vue虚拟滚动实现

虚拟滚动是一种优化长列表渲染性能的技术,通过仅渲染可视区域内的元素来减少DOM节点数量。以下是基于Vue的虚拟滚动实现方法:

使用第三方库

推荐使用成熟的虚拟滚动库如vue-virtual-scrollervue-virtual-scroll-list

安装vue-virtual-scroller

npm install vue-virtual-scroller

基本使用示例:

<template>
  <RecycleScroller
    class="scroller"
    :items="items"
    :item-size="50"
    key-field="id"
  >
    <template v-slot="{ item }">
      <div class="item">{{ item.name }}</div>
    </template>
  </RecycleScroller>
</template>

<script>
import { RecycleScroller } from 'vue-virtual-scroller'
import 'vue-virtual-scroller/dist/vue-virtual-scroller.css'

export default {
  components: { RecycleScroller },
  data() {
    return {
      items: Array(10000).fill().map((_, i) => ({ id: i, name: `Item ${i}` }))
    }
  }
}
</script>

<style>
.scroller {
  height: 400px;
}
.item {
  height: 50px;
  padding: 10px;
}
</style>

手动实现虚拟滚动

对于需要自定义实现的情况,可通过以下方式:

<template>
  <div class="virtual-list" @scroll="handleScroll" ref="container">
    <div class="phantom" :style="{ height: totalHeight + 'px' }">
      <div 
        class="content" 
        :style="{ transform: `translateY(${startOffset}px)` }"
      >
        <div 
          v-for="item in visibleData" 
          :key="item.id" 
          class="list-item"
          :style="{ height: itemSize + 'px' }"
        >
          {{ item.value }}
        </div>
      </div>
    </div>
  </div>
</template>

<script>
export default {
  props: {
    listData: Array,
    itemSize: {
      type: Number,
      default: 50
    },
    visibleCount: {
      type: Number,
      default: 10
    }
  },
  data() {
    return {
      startIndex: 0,
      endIndex: this.visibleCount
    }
  },
  computed: {
    totalHeight() {
      return this.listData.length * this.itemSize
    },
    visibleData() {
      return this.listData.slice(this.startIndex, this.endIndex)
    },
    startOffset() {
      return this.startIndex * this.itemSize
    }
  },
  methods: {
    handleScroll() {
      const scrollTop = this.$refs.container.scrollTop
      this.startIndex = Math.floor(scrollTop / this.itemSize)
      this.endIndex = this.startIndex + this.visibleCount
    }
  }
}
</script>

<style>
.virtual-list {
  height: 500px;
  overflow-y: auto;
  position: relative;
}
.phantom {
  position: absolute;
  left: 0;
  right: 0;
  top: 0;
}
.content {
  position: absolute;
  left: 0;
  right: 0;
}
.list-item {
  border-bottom: 1px solid #eee;
  display: flex;
  align-items: center;
  padding: 0 16px;
}
</style>

性能优化要点

  • 使用transform代替top进行定位,避免重排
  • 合理设置缓冲区,提前加载可视区域外的部分数据
  • 对于动态高度项目,需要实现尺寸测量和位置缓存
  • 使用requestAnimationFrame优化滚动事件处理

动态高度处理

对于不定高度的项目,需要先测量并缓存高度:

vue虚拟滚动实现

// 在mounted中测量初始高度
mounted() {
  this.cachedHeights = []
  this.$nextTick(() => {
    const items = this.$el.querySelectorAll('.list-item')
    items.forEach((item, index) => {
      this.cachedHeights[index] = item.getBoundingClientRect().height
    })
    this.calculatePositions()
  })
},
methods: {
  calculatePositions() {
    this.positions = this.listData.map((_, index) => {
      const prevPosition = this.positions[index - 1] || { top: 0, bottom: 0 }
      return {
        top: prevPosition.bottom,
        bottom: prevPosition.bottom + (this.cachedHeights[index] || this.defaultHeight)
      }
    })
    this.totalHeight = this.positions[this.positions.length - 1].bottom
  }
}

以上实现方式可根据具体需求选择,第三方库适合快速实现,手动实现则提供更高灵活性。

标签: vue
分享给朋友:

相关文章

vue实现右下角弹框

vue实现右下角弹框

实现右下角弹框的基本思路 在Vue中实现右下角弹框,通常需要结合CSS定位和Vue的组件化特性。弹框可以通过绝对定位固定在右下角,并通过Vue控制其显示与隐藏。 创建弹框组件 新建一个Vue组件(如…

vue广告实现

vue广告实现

Vue 广告实现方法 在 Vue 项目中实现广告功能可以通过多种方式完成,具体取决于广告类型和需求。以下是几种常见的实现方法: 使用第三方广告平台 许多广告平台如 Google AdSense、百…

vue实现建模

vue实现建模

Vue 实现建模的方法 在 Vue 中实现建模通常涉及数据绑定、组件化和状态管理。以下是几种常见的方法: 数据驱动建模 Vue 的核心是数据驱动视图。通过定义数据模型,Vue 会自动更新 DOM。例…

vue实现拍照

vue实现拍照

Vue实现拍照功能 在Vue中实现拍照功能通常需要结合浏览器的MediaDevices API和Canvas元素。以下是具体实现方法: 安装依赖(可选) 如果需要更简单的封装,可以安装vue-web…

vue实现机制

vue实现机制

Vue 实现机制的核心原理 Vue.js 的核心实现机制主要基于响应式系统、虚拟 DOM 和组件化设计。以下是关键实现细节: 响应式系统 Vue 通过 Object.defineProperty(V…

vue 实现排序

vue 实现排序

Vue 实现排序的方法 使用计算属性实现排序 通过计算属性对数组进行排序,可以保持原始数据不变。示例代码展示了如何对列表按名称升序排序: <template> <div>…