虚拟列表
懒加载列表
虚拟列表:一次性获取全部数据,但是只显示一部分
只渲染start和end之间的数据,使用translate3d实现在y轴滚动的效果。
终极目标
- 求出在可视区域显示的数据
- 求出滚动列表在y轴的偏移量
- 计算需要的变量
itemHeight: 单个元素的高度
visbleCount: 可显示的行数
offestStart: 在Y轴的偏移量 列表在页面中距离顶部的高度
listHeight: 列表的总长度
mounted() {
//元素内部高度
this.screenHeight = this.$el.clientHeight;
this.start = 0;
this.end = this.start + this.visbleCount;
},
computed: {
//总共列表的长度
listHeight() {
return this.listData.length * this.itemHeight;
},
//可视区域的数据
visableData() {
return this.listData.slice(
this.start,
Math.min(this.end, this.listData.length)
);
},
//可视区域中元素的个数
visbleCount() {
return Math.ceil(this.screenHeight / this.itemHeight);
},
//通过css让列表在Y轴偏移
getTransform() {
return `translate3d(0,${this.offestStart}px,0)`;
},
},
- 监听scroll事件
在滚动时,start、end、offsetStart都在变
得到开始和结束位置的索引值=>可视元素的集合,和偏移量=>在y轴需要移动的距离。
scrollHandler() {
//当前滚动位置
let scrollTop = this.$refs.list.scrollTop;
//开始索引
this.start = Math.floor(scrollTop / this.itemHeight);
this.end = this.start + this.visbleCount;
this.offestStart = scrollTop - (scrollTop % this.itemHeight);
},
3.html
<div class="container" @scroll="scrollHandler" ref="list">
<!-- 占位,让内容的高度超出容器的高度,从而产生滚动条 -->
<div
class="wrapper"
:style="{
height: listHeight + 'px',
}"
></div>
<div class="itemScreen" :style="{ transform: getTransform }">
<div
ref="items"
v-for="item in visableData"
:key="item.id"
:style="{ height: itemHeight + 'px', lineHeight: itemHeight + 'px' }"
>
{{ item.data }}
</div>
</div>
</div>

浙公网安备 33010602011771号