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


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

    1、页面监听版(简单)

    在mounted里监听页面滚动

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

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

    监听页面滚动事件

    • 获取当前滚动的高度scrollTop(代码里这种写法好好理解并记忆,囊括了各种情况);

    • 获取当前可视高度clientHeight;

    • 获取当前整个页面(包括可滚动区域,其实就是滚动的整个盒子)的高度scrollHeight;

    • scrollTop + clientHeight >= scrollHeight时即可证明滑到底部了;

      • 这里减二是为了消除像素在浏览器里显示时候出现的小小误差;
    • 滑动到底部看当前是否有更多数据(hasMore)可获得以及当前是否正在获取数据(busy)

    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)函数

    • 设置当前处于正在加载状态(busy置为true),其实相当于加了把锁(最近学os学傻了...;
    • 获取更多数据,且在回调里将加载状态消除。
    loadMore () {
      this.busy = true
      this.page++
      this.getJobList()
        .then(() => {
          this.busy = false
        })
    }
    

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

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

    • 监听页面的touchstart和touchend事件

    • 在touchstart中记录下手指开始滑动的位置;

    • 在touchend中记录下手指结束滑动的位置;

    • 将开始和结束位置进行比较:

      • 先判断滑动方向(上拉刷新,下拉加载),这一步还挺复杂 主要是判断手指的各种滑动情况比较复杂;
      • 若是上拉就看是否滑到底部,这一步的话主要是计算各种盒子的高度比较麻烦思路其实不难,难在布局;
      • 若是下拉就看当前距离顶部的高度(其实就是上面简单版里的scrollTop),若为0了说明回到原位,开始刷新。

    附源代码:

    <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{
    	 100%;
    	height: auto;
    	overflow: hidden;
    	margin-bottom: 10px;
    }
    .refreshLoading{
    	 20px;
    	height:20px;
    }
    .loadmoreBox{
    	 100%;
    	height:auto;
    }
    .loadmore{
    	 100%;
    	height: 30px;
    	text-align: center;
    	line-height: 30px;
    	font-size: 14px;
    	color: #666666;
    }
    </style>
    
    
  • 相关阅读:
    前端数据可视化插件(二)图谱
    前端数据可视化插件(一)图表
    CSS性能优化
    HTML性能优化
    github前端资源
    javascript生成n至m的随机整数
    原生js获取元素样式
    模式二之框架模式
    kendo-ui的使用和开发自己的组件
    pycharm安装报错Non-zero exit co?
  • 原文地址:https://www.cnblogs.com/TRY0929/p/14147607.html
Copyright © 2020-2023  润新知