当前位置:首页 > VUE

vue虚拟滚动实现

2026-02-17 11:09:02VUE

vue虚拟滚动实现

虚拟滚动(Virtual Scrolling)是一种优化长列表渲染性能的技术,通过仅渲染可见区域内的元素来减少DOM节点数量。以下是几种常见的实现方式:

使用第三方库

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

安装 vue-virtual-scroller

npm install vue-virtual-scroller

基本用法:

<template>
  <RecycleScroller
    class="scroller"
    :items="items"
    :item-size="32"
    key-field="id"
    v-slot="{ item }"
  >
    <div class="user">
      {{ item.name }}
    </div>
  </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.from({ length: 10000 }, (_, i) => ({ id: i, name: `User ${i}` }))
    }
  }
}
</script>

<style>
.scroller {
  height: 400px;
}
</style>

手动实现虚拟滚动

对于需要自定义的场景,可以手动实现虚拟滚动逻辑。

<template>
  <div class="virtual-scroll" @scroll="handleScroll" ref="scrollElement">
    <div class="scroll-content" :style="{ height: totalHeight + 'px' }">
      <div
        v-for="item in visibleItems"
        :key="item.id"
        class="item"
        :style="{ transform: `translateY(${item.offset}px)` }"
      >
        {{ item.content }}
      </div>
    </div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      items: Array.from({ length: 10000 }, (_, i) => ({
        id: i,
        content: `Item ${i}`,
        height: 50 // 假设每个项目高度固定
      })),
      visibleStartIndex: 0,
      visibleEndIndex: 0,
      scrollTop: 0
    }
  },
  computed: {
    totalHeight() {
      return this.items.reduce((sum, item) => sum + item.height, 0)
    },
    visibleItems() {
      return this.items
        .slice(this.visibleStartIndex, this.visibleEndIndex)
        .map(item => ({
          ...item,
          offset: this.items
            .slice(0, item.id)
            .reduce((sum, i) => sum + i.height, 0)
        }))
    }
  },
  mounted() {
    this.updateVisibleItems()
  },
  methods: {
    handleScroll() {
      this.scrollTop = this.$refs.scrollElement.scrollTop
      this.updateVisibleItems()
    },
    updateVisibleItems() {
      const { scrollTop } = this
      const viewportHeight = this.$refs.scrollElement.clientHeight
      let startIndex = 0
      let endIndex = 0
      let currentHeight = 0

      // 计算可见区域的起始索引
      for (let i = 0; i < this.items.length; i++) {
        if (currentHeight >= scrollTop) {
          startIndex = i
          break
        }
        currentHeight += this.items[i].height
      }

      // 计算可见区域的结束索引
      currentHeight = 0
      for (let i = startIndex; i < this.items.length; i++) {
        if (currentHeight > scrollTop + viewportHeight) {
          break
        }
        endIndex = i
        currentHeight += this.items[i].height
      }

      // 增加缓冲项
      const buffer = 5
      this.visibleStartIndex = Math.max(0, startIndex - buffer)
      this.visibleEndIndex = Math.min(this.items.length - 1, endIndex + buffer)
    }
  }
}
</script>

<style>
.virtual-scroll {
  height: 500px;
  overflow-y: auto;
  position: relative;
}

.scroll-content {
  position: relative;
}

.item {
  position: absolute;
  width: 100%;
  height: 50px;
  box-sizing: border-box;
  border-bottom: 1px solid #eee;
}
</style>

动态高度处理

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

vue虚拟滚动实现

methods: {
  measureItems() {
    this.$nextTick(() => {
      const nodes = this.$refs.items
      nodes.forEach((node, index) => {
        this.items[index].height = node.clientHeight
      })
    })
  }
}

性能优化技巧

  • 使用 requestAnimationFrame 节流滚动事件
  • 对于固定高度的项目,可以跳过测量步骤
  • 合理设置缓冲区域大小,平衡性能与用户体验
  • 考虑使用 Object.freeze 冻结不需要响应式的数据

以上方法可以根据具体需求选择使用,第三方库通常提供更完善的解决方案,而手动实现则更适合特殊定制场景。

标签: vue
分享给朋友:

相关文章

vue实现公式

vue实现公式

在Vue中实现公式展示或计算可以通过多种方式实现,以下为具体方法: 使用模板插值与计算属性 若公式较简单,可直接在模板中使用插值表达式或计算属性。例如计算圆的面积: <templat…

vue实现通知

vue实现通知

Vue 实现通知功能的方法 使用 Vue 实现通知功能可以通过多种方式实现,以下是一些常见的方法: 使用 Vue 的全局事件总线 在 Vue 中可以通过事件总线实现通知功能。创建一个全局事件总线,然…

vue搜索实现

vue搜索实现

Vue 搜索功能实现方法 基于计算属性的搜索 在 Vue 中可以通过计算属性实现简单的搜索功能。这种方式适合小型数据集,利用 JavaScript 的 filter 方法进行筛选。 data() {…

vue实现链接

vue实现链接

Vue 实现链接的方法 在 Vue 中实现链接可以通过多种方式,包括使用 <router-link>、<a> 标签或编程式导航。以下是几种常见的方法: 使用 <rout…

lua 实现vue

lua 实现vue

在 Lua 中实现类似 Vue 的响应式框架需要模拟 Vue 的核心功能,包括数据绑定、模板渲染和依赖追踪。以下是实现的关键思路和代码示例: 响应式数据绑定 使用 Lua 的 __index 和 _…

vue实现追加

vue实现追加

追加数据到数组或列表 在Vue中追加数据到数组或列表,可以通过push方法或concat方法实现。以下是几种常见的实现方式: 方法一:使用push方法 this.items.push(newIte…