前端虚拟列表

使用场景: 在移动端使用下拉加载数据的时候,随着不断从服务端拉取数据,数据列表内容越来越多,导致创建了很多的节点,这个时候vue的diff就需要对比很多次,造成性能消耗和内存占用。

虚拟列表的实现分两种:

  • 列表项高度固定

  • 列表项高度动态

高度固定实现过程:

  • 容器高度(可视区高度):viewport

  • 列表项高度:itemSize

  • 可视区域展示列表个数: viewCount

  • 列表长度:phantomHeight (itemSize * 列表个数)

  • 第一个元素顶部的距离:startOffset

  • 开始元素的下标: startIndex

  • 结尾元素的下标: endIndex

关键点就是确定需要渲染的列表个数,然后根据滚动时动态改变startIndex、endIndex、startOffset值,然后对列表项数据进行过滤切割,获取需要渲染的数据列表。

v3+ts实现代码:

<template>
{{startIndex}}
{{endIndex}}
  <div class="viewport" @scroll="scrollListBox" ref="viewport">
    <div class="v-list" :style="{ height: phantomHeight + 'px', transform: `translateY(${startOffset}px)`}">
      <div class="v-list-item" v-for="item in filterData" :key="item.num">
        {{item.num}}
      </div>
    </div>
  </div>
</template>

<script setup lang='ts'>
import { PropType, ref, computed } from 'vue'
interface listItem {
  index: number,
  num: number
}
const props = defineProps({
  data: {
    type: Array as PropType<listItem[]>,
    default: () => {}
  }
})
const viewport = ref<HTMLElement>()
let startIndex = ref<number>(0)
let itemSize = 100
let viewCount = 10
let phantomHeight = itemSize * props.data.length

let startOffset = computed(() => {
  return startIndex.value * itemSize
})

let endIndex = computed(() => {
  return startIndex.value + viewCount
})
let filterData = computed(() => {
  return props.data.slice(startIndex.value, endIndex.value)
})
const scrollListBox = () => {
  startIndex.value = Math.floor((viewport.value?.scrollTop || 0) / itemSize)
}
</script>

<style scoped>
.viewport {
  width: 500px;
  height: 500px;
  overflow: scroll;
}
.v-list-item {
  height: 100px;
  width: 100%;
  background: #fff;
  color: #000;
  line-height: 100px;
  border-bottom: 1px solid #ccc;
}
</style>

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值