列表无限滚动(虚拟列表)

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了列表无限滚动(虚拟列表)相关的知识,希望对你有一定的参考价值。

列表无限滚动需要考虑两点:

  1. 数据太多,要做虚拟列表
  2. 下拉到底,继续加载数据并拼接之前的数据

虚拟列表

只展示可视区域内的列表项目,动态计算可视区域内的列表项,删除非可视区域列表项。

(1)首先确定dom结构

  • 第一层作为容器层(​​infinite-list-container​​),目的是监听列表滚动,记录滚动位置scrollTop。
  • 第二层作为占位层(​​infinite-list-phantom​​),根据实际列表的长度占位,撑开空间,形成滚动条
  • 第三层作为列表层(​​infinite-list​​),列表数据展示的可视化区域,需要用​​transform:translate3D(x,y,z)​​,这里的y指的是列表偏移量。

(2)监听数据

监听容器的scroll事件,获取滚动位置scrollTop

  • 可视区域高度:screenHeight
  • 列表每项高度:itemSize
  • 列表数据:listData
  • 当前滚动位置:scrollTop

(3)确定需要的数据

  • 滚动的位置:​​this.$ref.list.scrollTop​
  • 确定列表项的高度:​​itemSize = 100px​
  • 可视区域的列表项的总数:​​visableCount = Math.ceil(screenHeight / itemSize)​
  • 确定每次加载列表数据的条数: ​​listData.length​
  • 确定列表的实际的长度:​​listHeight = itemSize * listData.length​
  • 开始索引:​​start = Math.floor(scrollTop / itemSize)​
  • 结束索引:​​end = start + visableCount​
  • 偏移量:scrollTop - (scrollTop % itemSize)

(4)代码

<div class="infinite-list-container" ref="list" @scroll="scrollEvent">
<div class="scrollTopBtn" @click="scrollToTop" v-show="end > 20"> 回到顶部</div>
<div class="infinite-list-phantom" :style=" height: listHeight + px "></div>
<div class="infinite-list" :style=" transform: getTransform ">
<div class="infinite-list-item" v-for="item in visibleData" :key="item.id" @click="toDetail(item.id)" :style=" height: itemSize + px,lineHeight: itemSize + px ">
<div class="left-section">
item.title[0]
</div>
<div class="right-section">
<div class="title"> item.title </div>
<div class="desc"> item.content </div>
</div>
</div>
</div>
</div>
<script lang="ts">
import Vue, Component from "vue-property-decorator";
import Faker from "faker";

interface Data
title: string;
content: string;
id: number | string;

@Component
export default class VirtualList extends Vue
public readonly itemSize: number = 100;
public listData: Data[] = [];
// 可视区域高度
public screenHeight: number =
document.documentElement.clientHeight || document.body.clientHeight;
// 可显示的列表项数
public visibleCount: number = Math.ceil(this.screenHeight / this.itemSize);
// 偏移量
public startOffset: number = 0;
// 起始索引
public start: number = 0;
// 结束索引
public end: number = this.start + this.visibleCount;

public $refs:
list: any;
;
// 列表总高度
get listHeight()
return this.listData.length * this.itemSize;


// 偏移量对应的style
get getTransform()
return `translate3d(0,$this.startOffsetpx,0)`;


// 获取真实显示列表数据
get visibleData()
return this.listData.slice(
this.start,
Math.min(this.end, this.listData.length)
);

// 获取数据
getTenListData()
if (this.listData.length >= 200)
return [];

return new Array(10).fill().map((item) => (
id: Faker.random.uuid(),
title: Faker.name.title(),
content: Faker.random.words(),
));

//初始化
created()
this.listData = this.getTenListData();

//滚动顶部
scrollToTop()
this.$refs.list.scrollTo(
top: 0,
left: 0,
behavior: "smooth",
);

//监听滚动事件
public scrollEvent(e: any)
// 当前滚动位置
const scrollTop = this.$refs.list.scrollTop;
// 此时的开始索引
this.start = Math.floor(scrollTop / this.itemSize);
// 此时的结束索引
this.end = this.start + this.visibleCount;
//拼接数据
if (this.end > this.listData.length)
this.listData = this.listData.concat(this.getTenListData());

// 此时的偏移量
this.startOffset = scrollTop - (scrollTop % this.itemSize);


</script>

(5)图示

列表无限滚动(虚拟列表)_虚拟列表

以上是关于列表无限滚动(虚拟列表)的主要内容,如果未能解决你的问题,请参考以下文章

Vue3 实现列表虚拟滚动

cocos creator 虚拟列表

前端性能优化分析

在 ScrollView 内创建列表

Vue如何渲染十万行数据(虚拟长列表)

UGUI 实现无限滚动