searchusermenu
  • 发布文章
  • 消息中心
点赞
收藏
评论
分享
原创

虚拟列表

2023-06-12 02:36:02
12
0

一、说明

1、使用场景

       当页面需要展示大量数据时,如果直接将大量数据渲染到页面上,会导致网页性能变差,加载时间变长,甚至出现卡顿等问题。此时使用虚拟列表,可以通过动态计算和渲染可见区域内的数据,来优化性能并提高用户体验。


2、虚拟列表实现

     可以基于组件库的虚拟滚动组件,如 vue-virtual-scroll-list(https://github.com/tangbc/vue-virtual-scroll-list)、vue-virtual-scroller(https://github.com/Akryum/vue-virtual-scroller/tree/master) 等实现,也可手写实现,基本思路是通过计算可视区域内需要渲染的数据项的索引范围,只对这些数据项进行渲染。

二、手写一个简单的虚拟列表


1、实现步骤

  1)定义可视区域div,固定其高度,通过overflow使其允许纵向Y轴滚动。定义整体高度div撑开高度,显示滚动条。遍历可视数据项
  2)定义一些基本的数据和参数,如原始数据、每项的高度、可见项数、缓存项数等。
  3)计算列表的总高度和初始显示的数据,并将其赋值给相应的变量。
  4)在onScroll方法中监听滚动事件,更新滚动距离并重新计算显示的数据。

2、代码

<template>
  <div ref="scroll" :style="{ height: `${contentHeight}px` }" class="scroll" @scroll="onScroll">
    <!--撑开高度,让滚动条出现-->
    <div :style="{ height: totalHeight + 'px' }">
      <!--数据项渲染区域-->
      <div :style="{ transform: 'translateY(' + offsetY + 'px)' }">
        <div v-for="(item, index) in visibleData" :key="index" class="item">
          {{ item.name + ' - ' + item.age }}
        </div>
      </div>
    </div>
  </div>
</template>

<script>
  export default {
    data() {
      return {
        data: [], // 原始数据
        visibleData: [], // 显示的数据
        contentHeight: 0, // 可视区域高度
        itemHeight: 50, // 每项的高度
        visibleCount: 10, // 可见项数
        bufferCount: 3, // 缓冲项数,避免滑动太快出现白屏
        offsetY: 0, // 滚动距离
        totalHeight: 0 // 总高度
      }
    },
    mounted() {
      this.contentHeight = this.itemHeight * this.visibleCount
      // 测试数据
      this.data = [...new Array(10000).keys()].map((i) => ({
        id: i + 1,
        name: `User ${i + 1}`,
        age: `Age ${Math.floor(Math.random() * (60 - 20 + 1)) + 20}`
      }))
      this.calculateTotalHeight()
      this.calculateVisibleData()
    },
    methods: {
      // 计算总高度
      calculateTotalHeight() {
        this.totalHeight = this.data.length * this.itemHeight
      },
      // 计算显示的数据
      calculateVisibleData() {
        const start = Math.floor(this.offsetY / this.itemHeight)
        const end = Math.min(start + this.visibleCount + this.bufferCount, this.data.length)

        this.visibleData = this.data.slice(start, end)
      },
      // 监听滚动事件
      onScroll() {
        this.offsetY = this.$refs.scroll.scrollTop
        this.calculateVisibleData()
      }
    }
  }
</script>
<style scoped>
  .scroll {
    overflow: auto;
    width: 700px;
    border: 1px solid rgb(7, 84, 226);
  }
  /*每条数据的样式*/
  .item {
    height: 50px;
    padding: 5px;
    color: #666;
    box-sizing: border-box;
  }
</style>

3、效果展示

 

0条评论
0 / 1000
小卡拉米
4文章数
1粉丝数
小卡拉米
4 文章 | 1 粉丝
小卡拉米
4文章数
1粉丝数
小卡拉米
4 文章 | 1 粉丝
原创

虚拟列表

2023-06-12 02:36:02
12
0

一、说明

1、使用场景

       当页面需要展示大量数据时,如果直接将大量数据渲染到页面上,会导致网页性能变差,加载时间变长,甚至出现卡顿等问题。此时使用虚拟列表,可以通过动态计算和渲染可见区域内的数据,来优化性能并提高用户体验。


2、虚拟列表实现

     可以基于组件库的虚拟滚动组件,如 vue-virtual-scroll-list(https://github.com/tangbc/vue-virtual-scroll-list)、vue-virtual-scroller(https://github.com/Akryum/vue-virtual-scroller/tree/master) 等实现,也可手写实现,基本思路是通过计算可视区域内需要渲染的数据项的索引范围,只对这些数据项进行渲染。

二、手写一个简单的虚拟列表


1、实现步骤

  1)定义可视区域div,固定其高度,通过overflow使其允许纵向Y轴滚动。定义整体高度div撑开高度,显示滚动条。遍历可视数据项
  2)定义一些基本的数据和参数,如原始数据、每项的高度、可见项数、缓存项数等。
  3)计算列表的总高度和初始显示的数据,并将其赋值给相应的变量。
  4)在onScroll方法中监听滚动事件,更新滚动距离并重新计算显示的数据。

2、代码

<template>
  <div ref="scroll" :style="{ height: `${contentHeight}px` }" class="scroll" @scroll="onScroll">
    <!--撑开高度,让滚动条出现-->
    <div :style="{ height: totalHeight + 'px' }">
      <!--数据项渲染区域-->
      <div :style="{ transform: 'translateY(' + offsetY + 'px)' }">
        <div v-for="(item, index) in visibleData" :key="index" class="item">
          {{ item.name + ' - ' + item.age }}
        </div>
      </div>
    </div>
  </div>
</template>

<script>
  export default {
    data() {
      return {
        data: [], // 原始数据
        visibleData: [], // 显示的数据
        contentHeight: 0, // 可视区域高度
        itemHeight: 50, // 每项的高度
        visibleCount: 10, // 可见项数
        bufferCount: 3, // 缓冲项数,避免滑动太快出现白屏
        offsetY: 0, // 滚动距离
        totalHeight: 0 // 总高度
      }
    },
    mounted() {
      this.contentHeight = this.itemHeight * this.visibleCount
      // 测试数据
      this.data = [...new Array(10000).keys()].map((i) => ({
        id: i + 1,
        name: `User ${i + 1}`,
        age: `Age ${Math.floor(Math.random() * (60 - 20 + 1)) + 20}`
      }))
      this.calculateTotalHeight()
      this.calculateVisibleData()
    },
    methods: {
      // 计算总高度
      calculateTotalHeight() {
        this.totalHeight = this.data.length * this.itemHeight
      },
      // 计算显示的数据
      calculateVisibleData() {
        const start = Math.floor(this.offsetY / this.itemHeight)
        const end = Math.min(start + this.visibleCount + this.bufferCount, this.data.length)

        this.visibleData = this.data.slice(start, end)
      },
      // 监听滚动事件
      onScroll() {
        this.offsetY = this.$refs.scroll.scrollTop
        this.calculateVisibleData()
      }
    }
  }
</script>
<style scoped>
  .scroll {
    overflow: auto;
    width: 700px;
    border: 1px solid rgb(7, 84, 226);
  }
  /*每条数据的样式*/
  .item {
    height: 50px;
    padding: 5px;
    color: #666;
    box-sizing: border-box;
  }
</style>

3、效果展示

 

文章来自个人专栏
数据结构
4 文章 | 1 订阅
0条评论
0 / 1000
请输入你的评论
0
0