uni-app小程序中做页面滚动底部或顶部加载效果

在移动应用开发中,无限滚动加载是一个常见的功能,用户可以通过滑动屏幕来加载更多的内容,从而提高应用的用户体验。本文将介绍如何使用Uniapp实现无限滚动加载的功能。

概述

我们需要实现的无限滚动加载功能的具体效果如下:

  1. 当用户滑动到底部时,自动加载更多的数据。

  2. 在加载数据时,显示一个加载动画,防止用户误以为应用已经崩溃。

  3. 当所有数据都已经加载完毕时,提示用户“没有更多数据了”。

方案

我们可以通过以下步骤来实现无限滚动加载功能:

  1. cs.vue组件中,使用uni.createIntersectionObserver()方法创建一个交叉观察器,用于观察加载动画是否进入了用户的视图区域。

  2. 在交叉观察器的回调函数中,判断加载动画是否进入了用户的视图区域,并根据需要加载更多的数据。

  3. 在加载数据时,使用事件来控制加载动画的出现与隐藏。

  4. 当所有数据都已经加载完毕时,使用事件来控制“没有更多数据了”的提示是否显示。

  5. index.vue组件中,引入cs.vue组件,并通过事件来控制加载动画和“没有更多数据了”的提示是否显示。

实现

cs.vue组件中,我们需要使用事件来控制加载动画的出现与隐藏。具体来说,当交叉观察器的回调函数中判断需要加载数据时,我们需要通过$emit方法触发一个名为aaa的事件,并传递参数0,表示加载动画需要出现。当数据加载完毕后,我们再次触发aaa事件,并传递参数1,表示加载动画需要消失。代码如下:

if (res.intersectionRatio > 0) {
  this.$emit("aaa", 0); // 加载动画出现
  setTimeout(() => {
    this.a += 10;
    this.$emit("aaa", 1); // 加载动画消失
  }, 3000)
}

cs.vue组件中,我们还需要使用事件来控制“没有更多数据了”的提示是否显示。具体来说,当所有数据都已经加载完毕时,我们需要通过$emit方法触发一个名为aaa的事件,并传递参数2,表示“没有更多数据了”的提示需要显示。代码如下:

if (this.a > 50) return this.$emit("aaa", 2);

index.vue组件中,我们需要引入cs.vue组件,并通过事件来控制加载动画和“没有更多数据了”的提示是否显示。具体来说,我们需要监听aaa事件,并根据传递的参数来控制加载动画和“没有更多数据了”的提示是否显示。代码如下:

<template>
  <view class="container">
    <text>{{appear === 0 ? '小球出现' : '小球消失'}}</text>{{appear}}
    <view class="page-section">
      <scroll-view class="scroll-view" scroll-y>
        <cs :appear="appear" @aaa="(val) => appear=val"></cs>
      </scroll-view>
    </view>
  </view>
</template>

<script>
	import cs from './cs.vue';
	let observer = null;
	export default {
		components: {
			cs
		},
		data() {
			return {
				appear: 1
			}
		},

	}
</script>

最后,为了避免内存泄漏,我们需要在cs.vue组件销毁时将交叉观察器断开连接。具体来说,我们需要在onUnload生命周期函数中使用disconnect()方法将交叉观察器断开连接。代码如下:

onUnload() {
  if (observer) {
    observer.disconnect()
  }
}

至此,我们就完成了无限滚动加载的实现。完整代码如下:

cs.vue组件代码:

<template>
	<view>
		<view class="item" v-for="item of a" :key="item">
			{{item}}锄禾日当午
		</view>
		<qiuy-loading class="ball" :class="{'is':appear===0}"></qiuy-loading>
		<view v-show="appear===2">
			没有数据了
		</view>
	</view>
</template>

<script>
	let observer = null;
	import QiuyLoading from './QiuyLoading.vue'
	export default {
		components: {
			QiuyLoading
		},
		props: ["appear"],
		data() {
			return {
				a: 20
			}
		},
		mounted() {
			observer = uni.createIntersectionObserver(this);
			observer.relativeTo('.scroll-view').observe('.ball', (res) => {

				// 当a》50时,停止加载
				if (this.a > 50) return this.$emit("aaa", 2);
				// 如果当前状态已经在加载中,则不进行。
				if (this.appear !== 1) return;
				// 出现了
				if (res.intersectionRatio > 60) {
					// 先让加载动画显示出来
					this.$emit("aaa", 0);
					setTimeout(() => {
						this.a += 10;
						// 加载出了数据,关闭加载动画
						this.$emit("aaa", 1);
					}, 3000)
				}
			})
		},
		onUnload() {
			if (observer) {
				observer.disconnect()
			}
		}
	}
</script>

<style>
	.notice {
		margin-top: 150rpx;
		margin: 150rpx 0 400rpx 0;
	}

	.is {
		height: auto;
		overflow: hidden;
	}

	.item {
		line-height: 100rpx;
		font-size: 40rpx;
	}
</style>

index.vue组件代码:

<template>
	<view class="container">
		<text>{{appear === 0 ? '小球出现' : '小球消失'}}</text>{{appear}}
		<view class="page-section">
			<scroll-view class="scroll-view" scroll-y>
				<cs :appear="appear" @aaa="(val) => appear=val"></cs>
			</scroll-view>
		</view>

	</view>
</template>
<script>
	import cs from './cs.vue';
	let observer = null;
	export default {
		components: {
			cs
		},
		data() {
			return {
				appear: 1
			}
		},
	}
</script>
<style>
	.scroll-view {
		height: 800rpx;
		background: #fff;
		border: 1px solid #ccc;
		box-sizing: border-box;
		/* padding-bottom: 30px; */
	}

	.scroll-area {
		height: 1300rpx;
		display: flex;
		flex-direction: column;
		align-items: center;
		transition: .5s;
	}
</style>

QiuyLoading.vue里的内容

<template>
	<view class="loader">
		<view class="l">L</view>
		<view class="o">o</view>
		<view class="a">a</view>
		<view class="d">d</view>
		<view class="i">i</view>
		<view class="n">n</view>
		<view class="g">g</view>
		<view class="d1">.</view>
		<view class="d2">.</view>
	</view>
</template>

<script>
</script>

<style>
	.loader {
		text-align: center;
		height: 0;
		overflow: hidden;
	}

	.is {
		height: auto;
		padding-bottom: 20rpx;
	}
</style>

最后,看下效果吧!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值