其他分享
首页 > 其他分享> > vue项目中自己实现下拉刷新和上拉加载

vue项目中自己实现下拉刷新和上拉加载

作者:互联网

vue项目中自己实现下拉刷新和上拉加载

1、页面监听版(简单)

在mounted里监听页面滚动

其实是只要监听滚动盒子的scroll事件即可,但有的时候滚动的是整个页面,那我们就直接监听window的滚动就可以:

window.addEventListener('scroll', this.onContentScroll)

监听页面滚动事件

onContentScroll (e) {
  let scrollTop = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop;
  let clientHeight = document.documentElement.clientHeight;
  let scrollHeight = document.documentElement.scrollHeight;
  if (scrollTop + clientHeight >= scrollHeight-2) {
    if (this.hasMore && !this.busy) {
      this.loadMore()
    }
  }
},

加载更多(loadMore)函数

loadMore () {
  this.busy = true
  this.page++
  this.getJobList()
    .then(() => {
      this.busy = false
    })
}

2、另写组件版(略复杂)

就不仔仔细细讲了,原理和上面的简单版差不多,只是扩充了一些内容以及加上手势操作。

附源代码:

<template>
	<div class="loadmoreBox flex flexh flexvc" @touchstart="touchStart($event)"  @touchend="touchEnd($event)">
		<div class="refreshBox flex flexc" v-if="refresh">
			<van-loading class="refreshLoading" type="spinner" />
		</div>
		<slot></slot>
		<div class="loadmore" v-if="status==1">上拉加载更多...</div>
		<van-loading class="loadmore" v-else-if="status==2" type="spinner" />
		<div class="loadmore" v-else-if="status==3">我是有底线的</div>
	</div>
</template>

<script>
import { Loading as VanLoading } from 'vant';
export default {
	name: 'LoadMore',
	props:{
		refresh:{
			type:Boolean,
			default:false
		},
		status:{
			type:Number,
			default:0
		}
	},
	data(){
		return {
			startX:0,
			startY:0,
		}
	},
	
	components:{
		VanLoading
	},
	methods:{
		touchStart(e){
			this.startY = e.targetTouches[0].pageY;
			this.startX = e.targetTouches[0].pageX;  
		},
		touchEnd(e){
			let endY = e.changedTouches[0].pageY;
			let endX = e.changedTouches[0].pageX; 
			let direct=this.getSlideDirection(this.startX,this.startY,endX,endY);
			console.log(direct);
			if(direct==1){ //上拉加载
				let isEnd=this.scrollToTheEnd();
				if(isEnd&&this.status==1){
					this.$emit('loadMore');
				}
			}else if(direct==2){ //下拉刷新
				// 获取滚动条距离顶部的距离
				let scrollToTop = document.documentElement.scrollTop || document.body.scrollTop || window.pageYOffset;
				if(!scrollToTop){
					this.$emit('onRefresh');
				}
			}	
		},
		/**
		* 判断滚动条是否到底
		*/
		scrollToTheEnd () {
			//获取窗口的高度
			let clientHeight = document.documentElement.clientHeight;
			//获取滚动元素距离文档 顶部的距离
			let elementTop=document.querySelector('.loadmoreBox').offsetTop;
			//获取滚动元素高度
			let elementHeight=document.querySelector('.loadmoreBox').offsetHeight;
			
			//获取顶部固定区域高度
			let topFixEl=document.querySelector('.topFixBlank');
			let topFixHeight=topFixEl?topFixEl.offsetHeight:0;
			
			//获取加载板块高度
			let loadmoreEl=document.querySelector('.loadmore');
			let loadmoreH=loadmoreEl?loadmoreEl.offsetHeight:0;
			// 获取滚动条距离顶部的距离
			let scrollToTop = document.documentElement.scrollTop || document.body.scrollTop || window.pageYOffset 
			// 获取滚动条的总高度
			let scrollHeight = document.documentElement.scrollHeight  || document.body.scrollHeight
			//整个列表的高度
			let pageHeight=elementTop+elementHeight-topFixHeight-loadmoreH;
			//判断是否到底
			if(pageHeight+Math.ceil(scrollToTop)>scrollHeight){ //如果列表高度+滚动距离大于滚动条高度,则代表到底了
				return true;
			}else{
				return false;
			}
		},
		/**
		* 返回角度
		*/
		getSlideAngle (dx, dy) {
			return Math.atan2(dy, dx) * 180 / Math.PI
		},
		/**
		 * 根据起点和终点返回方向 1:向上,2:向下,3:向左,4:向右,0:未滑动
		 * @param {number} startX X轴开始位置
		 * @param {number} startY X轴结束位置
		 * @param {number} endX Y轴开始位置
		 * @param {number} endY Y轴结束位置
		 */
		getSlideDirection (startX, startY, endX, endY) {
			let dy = startY - endY
			let dx = endX - startX
			let result = 0
			// 如果滑动距离太短
			if (Math.abs(dx) < 2 && Math.abs(dy) < 2) {
				return result
			}
			let angle = this.getSlideAngle(dx, dy)
			if (angle >= -30 && angle < 30) {
				result = 4
			} else if (angle >= 30 && angle < 150) {
				result = 1
			} else if (angle >= -150 && angle < -30) {
				result = 2
			} else if ((angle >= 150 && angle <= 180) || (angle >= -180 && angle < -150)) {
				result = 3
			}
			return result
		}
	}
}
</script>
<style lang="scss" scoped="scoped">
.refreshBox{
	width: 100%;
	height: auto;
	overflow: hidden;
	margin-bottom: 10px;
}
.refreshLoading{
	width: 20px;
	height:20px;
}
.loadmoreBox{
	width: 100%;
	height:auto;
}
.loadmore{
	width: 100%;
	height: 30px;
	text-align: center;
	line-height: 30px;
	font-size: 14px;
	color: #666666;
}
</style>

标签:vue,angle,let,&&,刷新,scrollTop,document,scrollHeight,加载
来源: https://www.cnblogs.com/TRY0929/p/14147607.html