uniapp封装虚拟列表滚动组件

发布于:2024-07-06 ⋅ 阅读:(23) ⋅ 点赞:(0)

uniapp封装虚拟列表滚动组件

这里用到一个列表,然后数据可能有很多很多…,一次性全部渲染到dom上会卡顿,很废性能,于是用了这个虚拟列表就变丝滑很多很多。

在这里插入图片描述

组件mosoweInventedList 代码:

<!-- 虚拟滚动列表组件:mosoweInventedList -->
<template>
	<view class="mosowe-invented-list">
		<scroll-view class="container" scroll-y :style="{ height: boxHeight + 'px' }" @scroll="handleScroll">
			<div class="mosowe-invented-wrap" :style="{ height: itemHeight * list.length + 'px' }">
				<div class="mosowe-invented-content" :style="{ transform: 'translateY(' + offsetY + 'px)' }">
					<view class="mosowe-invented-item" v-for="(item, index) in showList" :key="index">
						<slot :item="item"></slot>
					</view>
				</div>
			</div>
		</scroll-view>
	</view>
</template>

<script>
	export default {
		props: {
			list: {
				type: Array,
				default: () => []
			},
			cacheNum: {
				// 前后缓存数目
				type: Number,
				default: 10
			}
		},
		data() {
			return {
				showList: [], // 展示的数据列表
				boxHeight: 0, // 组件可视区高度
				itemHeight: 0, // 每条数据高度,计算第一条数据的高度,以第一条数据高度为主
				offsetY: 0
			};
		},
		computed: {
			pageNum() {
				if (this.boxHeight && this.itemHeight) {
					return Math.ceil(this.boxHeight / this.itemHeight) + this.cacheNum;
				} else {
					return this.cacheNum;
				}
			}
		},
		watch: {
			pageNum() {
				this.setShowList(0);
			},
			list: {
				handler() {
					this.init();
				},
				deep: true,
				immediate: true
			}
		},
		mounted() {
			this.init();
		},
		methods: {
			init() {
				this.$nextTick(() => {
					this.setShowList(0);
					let t = setTimeout(() => {
						clearTimeout(t);
						t = null;
						const query = uni.createSelectorQuery().in(this);
						query
							.select('.mosowe-invented-list')
							.boundingClientRect((res) => {
								this.boxHeight = Math.floor(res?.height) || 0;
							})
							.select('.mosowe-invented-item')
							.boundingClientRect((res) => {
								this.itemHeight = Math.floor(res?.height) || 0;
							})
							.exec();
					}, 100);
				});
			},
			handleScroll(e) {
				const scrollTop = Math.floor(e.detail.scrollTop);

				this.offsetY = scrollTop - (scrollTop % this.itemHeight);

				let startIndex = Math.floor(scrollTop / this.itemHeight);

				if (startIndex > this.cacheNum) {
					this.offsetY -= this.cacheNum * this.itemHeight;
					startIndex = startIndex - this.cacheNum;
				}

				this.setShowList(startIndex);

				this.$emit('scroll', scrollTop);
			},
			setShowList(startIndex) {
				this.showList = this.list.slice(startIndex, startIndex + this.pageNum);
			}
		}
	};
</script>

<style lang="scss" scoped>
	.mosowe-invented-list {
		overflow: hidden;
		height: 100%;
		width: 100%;

		.container {
			width: 100%;
			height: 100%;
		}
	}
</style>

使用:

<template>
	<view class="centent">
		<mosoweInventedList :list="listData" :cacheNum="20">
			<template #default="{ item }">
				<view class="item">
					<view class="list">
						<view class="col title">
							<image class="mark" src="@/static/images/layout/rectangle_9.png" mode=""></image>
							{{ item.yhmc }}
						</view>
						<view class="col area">
							<u-count-to fontSize="9rpx" style="color: #2EC38E;" class="unm" :endVal="item.mj"
								separator=","></u-count-to>
							<text class="unit">k㎡</text>
						</view>
						<view class="col time">
							{{ item.jmrq }}
						</view>
					</view>
					<u-divider text=""></u-divider>
				</view>
			</template>
		</mosoweInventedList>
	</view>
</template>

网站公告

今日签到

点亮在社区的每一天
去签到