虚拟列表:只加载可视区域的数据,通过计算长度区间反推需要加载的数据来实现假滑动。

<template>
	<scroll-view class="container" scroll-y="true" @scroll="scroll" >
		<!-- 虚拟列表总高度 -->
		<view :style="{'height': `${totalHeight}rpx`, 'position': 'relative'}">
			<!-- 可视渲染区 -->
			<view :style="{'top': `${top}px`}" style="width: 100%;position:absolute">
                <!--在这里自定义你数据的展示结构和样式,itemHeight为这里的总高度-->
				<view  v-for="(item,index) in showList" :key="index" class="item">
					<span>我是第{{item.index}}条数据</span>
				</view>
			</view>
		</view>
	</scroll-view>
</template>
 
<script>
export default {
	data(){
		return{
			allList:[],//原始数据列表
			//虚拟列表
			showList: [],  //可视区域显示的数据
			itemHeight: 100,//每条数据所占高度
			showNum: 0,  //可视区域显示的最大条数
			top: 0, //偏移量
			scrollTop: 0,  //卷起的高度
			startIndex: 0,  //可视区域第一条数据的索引
			endIndex: 0,  //可视区域最后一条数据的索引+1,
		}
	},
	onLoad() {
        //获取数据列表
		for(let i=0;i<100;i++){
			this.allList.push({'index':i})
		}
		// console.log(this.allList)
	},
	onShow() {
        //第一次时调用一下,且uni.createSelectorQuery()需要在生命周期mounted之后使用
		this.scroll()
	},
	computed: {
		totalHeight() {
			return this.allList.length*this.itemHeight*2//因为rpx和px的关系
		}
	},
	methods:{
	//虚拟列表
	getShowList(){
        //可视区域能出现的数据条数
		this.showNum = Math.ceil(this.contentHeight/this.itemHeight);  
		// console.log('可视数量',this.showNum)
 
        //可视区域第一条数据的索引
		this.startIndex = Math.floor(this.scrollTop/this.itemHeight);   
		// console.log('初始索引',this.startIndex)
 
        //可视区域最后一条数据的下一条数据
		this.endIndex = this.startIndex + this.showNum;
   	
        //可视区数据,会比实际可视多渲染一条		
        this.showList = this.allList.slice(this.startIndex, this.endIndex)  
		// console.log(this.showList)
 
        //保证滑动时第一条数据完整展示
		let offsetY = this.scrollTop - (this.scrollTop % this.itemHeight);  
 
		this.top = offsetY;
	},
	scroll(){
		// 利用uniapp提供的接口获取可视区域的高度和滚动高度
		let query=uni.createSelectorQuery()
		let container=query.select('.container');
		container.fields({
			// rect:true,   //是否返回节点布局位置信息{left,top,right,bottom}
			size:true,  //是否返回节点尺寸信息{width,height}
			scrollOffset:true //是否返回节点滚动信息{scrollLeft,scrollTop}
		},(res)=>{
			console.log(res)
			this.scrollTop=res.scrollTop
			this.contentHeight=res.height
			this.getShowList();//因为所在函数是异步
		}).exec()
	},
	}
}
</script>
 
<style>
	.container{
		width: 100%;
		height: 100vh;
        /*原生一定得有这个overflow的hidden效果,此处用了scroll-view所以不需要*/
		/*overflow:auto;*/
	}
	
	.item{
		/* 按照实际需求写css */
		width: 100%;
		height: 200rpx;/* 要对应上itemHeight */
		border: 1rpx solid slateblue;
	}
</style>