设置box 显示区域 达到区域内滚动 并监听滚动事件
代码如下:
<template>
<div class="box" ref="box" @scroll="handleScroll">
<ul class="list" ref="list" :style="{ transform: getTransform }">
<li class="item" v-for="(item, index) in visibaleData" :key="index">{{item}}{{index}}</li>
<div v-if="loadShow">加载中....</div>
</ul>
</div>
</template>
<style lang="scss" scoped>
.box {
width: 600px;
height: 60vh;
background: #fff;
position: relative;
overflow-y: scroll;
color: #4196FF;
.list {
width: 100%;
.item {
width: 100%;
height: 60px;
border: 1px solid #000;
box-sizing: border-box;
}
}
}
::-webkit-scrollbar{
display: none;
}
</style>
数据处理逻辑及初始化
获取真实数据 (list)
设置每一个列的高度值(itemHeight)
获取显示区域高度 (offsetHeight)
计算显示区域的数量 (visibaleCount)
记录可视区域的第一(startIndex)和最后一个元素(endIndex)
根据startIndex跟endIndex的值 计算可视区域起始到结束的数据赋值 (visibaleData)
监听滚动事件
利用 $refs 获取滚动距离(scroll = this.$refs.box.scrollTop)
计算滚动了多少个列(Math.floor(scroll / itemHeight))并修改startIndex的位置
startIndex值修改 即重新计算 endIndex 的值 = startIndex + visibaleCount
并手动设置滚动距离 getTransform
利用 endIndex 比对 list.length 进行数据加载 利用loadShow 实现节流if (this.endIndex > this.list.length)
最后重新计算可视区域渲染的数据 updateVisibleData()
备注:可视区高度可动态获取不固定 但是itemHeight每个列的高度得固定 这是弊端 有更好方法的请多多指点
代码如下:
<script>
export default {
data() {
return {
// offsetHeight: 600, //初始化可视区域高度
itemHeight: 60, //每个列的高度
visibaleCount: 0, //可视区域的渲染的个数
// allHeight: 0, //总数据的高度
visibaleData: [], //可视区域渲染的数据集合
list: [], //总数据
startIndex: 0, //可视区域的第一个元素
endIndex: 0, //可视区域的最后一个元素
bufferSize: 6, // 首次缓冲值
getTransform: 0, //滚动距离
loadShow: false, // 阻止多次触发
};
},
mounted() {
// 初始化数据
for (let i = 0; i < 10; i++) {
this.list.push("item");
}
this.init(true)
},
methods: {
// 初始化数据
init(first) {
if (first) {
// 动态获取显示区域的高度
// this.offsetHeight = this.$refs.box.offsetHeight
// 计算显示区域可以渲染的数量
this.visibaleCount =
Math.floor(this.$refs.box.offsetHeight / this.itemHeight) + this.bufferSize;
// 可视区域的最后一个元素
this.endIndex = this.startIndex + this.visibaleCount;
}
// 计算全部数据的高度
// this.allHeight = this.list.length * this.itemHeight;
this.updateVisibleData();
},
//可视区域渲染的数据
updateVisibleData() {
// 如果不显示.load 可this.endIndex+1 增加一个列的缓冲区域
this.visibaleData = this.list.slice(this.startIndex, this.endIndex);
},
// 滚动触发
handleScroll(e) {
if(this.loadShow) return
let scroll = this.$refs.box.scrollTop;
this.startIndex = Math.floor(scroll / this.itemHeight);
// 可视区域的最后一个元素
this.endIndex = this.startIndex + this.visibaleCount;
//让滚动距离为itemHeight整数倍,
this.getTransform = `translate3d(0,${scroll -
(scroll % this.itemHeight)}px,0)`;
console.log(scroll -
(scroll % this.itemHeight))
if (this.endIndex > this.list.length) {
this.loadShow = true
// 仿制数据加载
setTimeout(() => {
for (let i = 0; i < 10; i++) {
this.list.push("item");
}
this.loadShow = false
}, 1000)
return
}
this.updateVisibleData();
}
}
};
</script>
完整demohttps://download.csdn.net/download/weixin_39007040/85028960