uniapp:好用的上拉加载组件

hr-pull-load.vue

<template>
	<scroll-view scroll-y='true' :style="{height:height==-1?'100%':height+'rpx'}" @scrolltolower='loadMore' :lower-threshold='lowerThreshold' @touchstart="doTouchStart" @touchend="doTouchEnd" @touchmove="doTouchMove">
		<!-- 下拉提示 -->
		<view class="upDown" :style="{height: upDownTipsHeight+'px',maxHeight:maxHeight+'px'}" :class="isHeightChange?'heightAnimation':''">
			<text class="arrow" :class="upDownTipsHeight>=pullHeight?'upArrow':''" v-if="!isAllowLoading&&upDownTipsHeight>20">↓</text>
			<view class="loading" v-if="isAllowLoading">
				<text class="list"></text>
				<text class="list"></text>
				<text class="list"></text>
				<text class="list"></text>
				<text class="list"></text>
				<text class="list"></text>
				<text class="list"></text>
				<text class="list"></text>
			</view>
			<text class="tips">{{upDownTips}}</text>
		</view>
		<!-- 内容 -->
		<slot></slot>
		<!-- 底部提示 -->
		<view class='bottomTips' v-if="bottomTips">
			<view class="loading" v-if="bottomTips=='loading'">
				<text class="list"></text>
				<text class="list"></text>
				<text class="list"></text>
				<text class="list"></text>
				<text class="list"></text>
				<text class="list"></text>
				<text class="list"></text>
				<text class="list"></text>
			</view>
			<view>{{bottomTips | judgeBottomTips}}</view>
		</view>
	</scroll-view>
</template>

<script>
	export default{
		data(){
			return{
				upDownTipsHeight:0,//下拉时提示框的高度
				upDownTips:'',//下拉时提示框的文字内容
				startY:0,//第一次点击屏幕的Y坐标
				startX:0,//第一次点击屏幕的X坐标
				distanceY:0,//滑动的距离
				isAllowLoading:false,//下拉释放时是否显示loading样式
				isHeightChange:false,//下拉释放时提示框高度变化是否有动画
				isAllowPullDown:false,//是否触发下拉刷新
				isInterval:false,//防止鼠标或者手指移动时多次执行逻辑判断
			}
		},
		props: {
			height:{
				type:Number,
				default :700
			},
			pullHeight: {
				type: Number,
				default: 50
			},
			maxHeight: {
				type: Number,
				default: 100
			},
			bottomTips:{
				type: String,
				default: ''
			},
			lowerThreshold:{
				type: Number,
				default: 20
			},
			isTab:{
				type: Boolean,
				default: false
			},
			isAllowPull:{
				type: Boolean,
				default: true
			}
		},
		created() {
			//对传入的参数进行判断
			this.pullHeight<=20?this.pullHeight = 40:null;
			this.maxHeight<50?this.maxHeight = 50:null;
		},
		filters:{
			//判断底部提示文字
			judgeBottomTips(type){
				switch (type){
					case 'nomore':
						return '没有更多数据了'
						break;
					case 'loading':
						return '加载中...'
						break;
					case 'more':
						return '上拉加载更多'
						break;
					default:
						break;
				}
			}
		},
		methods:{
			//鼠标点击
			doTouchStart(e){
				if(!this.isAllowPull){
					return;
				}
				this.isHeightChange = false;
				this.isInterval = true;
				this.startY = e.touches[0].clientY;
				this.startX = e.touches[0].clientX;
			},
			//鼠标移动
			doTouchMove(e){
				if(!this.isAllowPull){
					return;
				}
				//滑动的距离
				this.distanceY = e.touches[0].clientY - this.startY;
				
				//只检测一次
				if(this.isInterval){
					this.isInterval = false;
					//这里判断横向滑动的距离差,主要是为了防止一个页面多个该组件时(横向tab切换),出现的误操作
					if(Math.abs(this.startX-e.touches[0].clientX)>5&&this.isTab){
						this.isAllowPullDown = false;
					}
					else{
						this.isAllowPullDown = true;
					}
				}
				
				//根据横向滑动的距离判断是否触发下拉
				if(!this.isAllowPullDown){
					return;
				}
				
				//提示框的高度
				this.upDownTipsHeight = this.distanceY;
				
				//根据提示框的高度提示不同的内容
				if(this.upDownTipsHeight<=20){
					this.upDownTips = '';
				}
				else if(this.upDownTipsHeight>20&&this.upDownTipsHeight<this.pullHeight){
					this.upDownTips = '下拉刷新';
				}
				else if(this.upDownTipsHeight>=this.pullHeight){
					this.upDownTips = '松开刷新';
				}
			},
			//鼠标松开
			doTouchEnd(e){
				if(!this.isAllowPull){
					return;
				}
				if(this.upDownTipsHeight>=this.pullHeight){
					this.isAllowLoading = true;
					this.upDownTips = '刷新中...';
					this.currentPage = 1;
					this.loadingType = "more";
					this.$emit('refresh',1);
				}
				else{
					this.distanceY = 0;
					this.upDownTipsHeight = 0;
					this.upDownTips = '';
				}
				this.isInterval = true;
				this.isAllowPullDown = false;
				this.isHeightChange = true;
				// console.log(e.changedTouches[0].clientY);
			},
			//重置
			reSet(){
				if(!this.isAllowPull){
					return;
				}
				this.isAllowLoading = false;
				this.upDownTips = '';
				this.upDownTipsHeight = 0;
				this.distanceY = 0;
				this.isInterval = true;
				this.isAllowPullDown = false;
			},
			loadMore(){
				this.$emit('loadMore');
			}
		}
	}
</script>

<style lang="scss" scoped>
	.loading{
		width: 110rpx;
		height: 110rpx;
		position: relative;
		transform: scale(.4);
		margin-right: -20rpx;
		.list {
			width:15rpx;
			height:15rpx;
			border-radius:30px;
			background:#090909;
			position:absolute;
			animation:opaticyAnimation linear 0.7s infinite;
			-webkit-animation:opaticyAnimation linear 0.7s infinite;
		}
		.list:nth-child(1) {
			left:24px;
			top:2px;
			animation-delay:0s;
		}
		.list:nth-child(2) {
			left:40px;
			top:8px;
			animation-delay:0.1s;
		}
		.list:nth-child(3) {
			left:47px;
			top:24px;
			animation-delay:0.2s;
		}
		.list:nth-child(4) {
			left:40px;
			top:40px;
			animation-delay:0.3s;
		}
		.list:nth-child(5) {
			left:24px;
			top:47px;
			animation-delay:0.4s;
		}
		.list:nth-child(6) {
			left:8px;
			top:40px;
			animation-delay:0.5s;
		}
		.list:nth-child(7) {
			left:2px;
			top:24px;
			animation-delay:0.6s;
		}
		.list:nth-child(8) {
			left:8px;
			top:8px;
			animation-delay:0.7s;
		}
		@keyframes opaticyAnimation{
			from{
				opacity: 1;
			}
			to{
				opacity: 0;
			}
		}
	}
	.heightAnimation{
		transition: all .2s linear;
	}
	.upDown{
		width: 100%;
		display: flex;
		justify-content: center;
		align-items: center;
		.arrow{
			font-size: 40rpx;
			margin-right: 10rpx;
		}
		.upArrow{
			transition: all .3s linear;
			transform: rotate(180deg);
		}
		.tips{
			font-size: 30rpx;
		}
	}
	.bottomTips{
		width: 100%;
		height: 120rpx;
		font-size: 30rpx;
		display: flex;
		justify-content: center;
		// 底部的提示语靠上显示,免得被tabBar挡住
		align-items:flex-start;
	}
	.loadingRotate{
		display: inline-block;
		font-size: 40rpx;
		animation: loadingAnimation 1s linear infinite;
	}
	@keyframes loadingAnimation{
		0%{
			transform: rotate(0);
		}
		100%{
			transform: rotate(360deg);
		}
	}
</style>

使用方法

<view class="main">
			<!-- 下拉加载数据插件 -->
			<view class="messageBox" @touchmove.stop.prevent :style="{height:height+'px'}" v-if="!isLoading">
			<hr-pull-load v-if="!isLoading" @refresh='refresh' @loadMore='loadMore' :height='-1' :pullHeight='50' :maxHeight='100'
			 :lowerThreshold='20' :bottomTips='bottomTips' :isTab='false' :isAllowPull="false" ref='hrPullLoad'>
			 <view class="tableData">
			 	<view class="item" v-for="item in tableData">
			 		<view class="top">
			 			<view class="txt">
			 				姓名:{{item.name}}
			 			</view>
			 			<view class="txt">
			 				手机号:
			 				<text class="txt-phone" @click="call(item.phone)">{{item.phone}}</text>
			 			</view>
			 		</view>
			 		
			 	</view>
			 	
			 </view>
			 </hr-pull-load>
			</view>
			
		</view>

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值