购物车页面,通过计算当前可视区域的商品和高度,用虚拟列表的方式只渲染可视区域内的数据
一个商品选项的高度
可视区域高度
展示商品的数量等于可视区域高度/一个商品选项的高度
滑动条距离顶部的距离
this.$el.clienHeight 水平滚动条的高度 (如果存在) ,不然就是屏幕高度
讲一讲实现实现过程
首先通过给元素添加ref,.clientHeight获得可视区域高度,再设置列表每项高度,获得当前页面可展示多少项
监听onScroll事件触发时,通过ref获取滚动离顶部的距离scrolltop,
改变开始项和结束项从全部列表取数据到页面上进行渲染
监听虚拟列表滚动更换可视区内容
<template>
<div id="app">
<!-- 包裹可视区域的可滚动的虚拟列表 -->
<div class="fictitious" @scroll="onScroll($event)" ref="ftwh" >
<!-- 占位元素,高度为总列表高度,提供滚动条,通过绝对定位脱离普通文档流不占父元素高度 -->
<div :style="{height: phantomHeight+'px'}" class="seize"></div>
<!-- 可视区域 -->
<div class="LookCant" :style="{transform: getTransform}">
<p v-for="item of lookArr" :key="item" :style="{height: rowHeight +'px'}" class="pp">
{{item}}
</p>
</div>
</div>
</div>
</template>
<script>
export default {
data(){
return {
//总列表数据
arr:[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99],
//可视高度
height: 0,
//列表元素高度
rowHeight: 100,
//开始索引
starItem:0,
//结束索引
endItem:0,
//滑动条离顶部距离
startOffset:0
}
},
methods: {
onScroll(){
if((this.$refs.ftwh.scrollTop/this.rowHeight+this.limit)>this.total){
this.endItem = this.total
return false
}
this.startOffset = this.$refs.ftwh.scrollTop
this.starItem = Math.floor(this.startOffset/this.rowHeight);
this.endItem = this.starItem+this.limit;
console.log(this.lookArr);
console.log(this.startOffset);
}
},
computed:{
// 总条数
total(){
return this.arr.length;
},
//列表总高度
phantomHeight(){
return this.arr.length*this.rowHeight;
},
//可视范围内可展示元素数量
limit(){
return Math.ceil(this.height/this.rowHeight)
},
//真实显示的列表数据
lookArr(){
return this.arr.slice(this.starItem,Math.min(this.arr.length,this.endItem));
},
getTransform(){
return `translate(0,${this.startOffset}px)`;
}
},
mounted() {
this.height = this.$el.clientHeight;
this.starItem = 0;
this.endItem = this.starItem+this.limit;
},
}
</script>
<style>
html{
height: 100%;
}
body{
margin: 0;
padding: 0;
height: 100%;
}
#app{
height: 100%;
}
.fictitious{
height: 100%;
position: relative;
overflow-y:auto;
}
.pp{
box-sizing: border-box;
padding: 10px 0;
text-align: center;
background-color: #999;
margin: 0;
border-bottom: 1px solid #fff;
line-height: 100px;
}
.seize{
z-index: -1;
position: absolute;
top: 0;
left: 0;
right: 0;
}
</style>