admin管理员组

文章数量:1516870

下拉刷新

效果展示

扫码体验

点击访问demo地址
点击查看源码

背景

下拉刷新是移动端经常会用到的功能,看了各种各样的ui库,自己想捣鼓一下,研究下其中的原理,于是便有了这个例子。

页面骨架

<template><div class="pullDown"><!--loading--><div class="pullDown__loading"></div><!--scroll content--><div class="pullDown__scroll"><ul class="pullDown__list"></ul></div></div>
</template>复制代码

页面基本样式

.pullDown{background-color: #fff;position: absolute;z-index: 1;width: 100%;height: 100%;overflow-y: scroll;/* 增加该属性,可以增加弹性 */-webkit-overflow-scrolling: touch;transform: translate3d(0, 0, 0);-webkit-transform: translate3d(0, 0, 0);    
}
.pullDonw__loading{position: absolute;left: 0;top: 0;display: block;overflow: hidden;width: 100%;height: 50px;text-align: center;padding: 16px 24px; z-index: 2;background-color: #fff;
}
.pullDown__scroll{position: relative;z-index: 10;background-color: #fff;border-bottom: 1px solid #e8e8e8;border-top: 1px solid #e8e8e8;
}
复制代码

核心实现

下拉刷新主要根据touchstart,touchmove,touchend三个事件进行判断操作。

  1. touchstar触发时,则判断刷新状态中和容器到达顶端的情况,否则记录当前位置信息并设置可拉动状态;
  2. touchemove触发时,判断刷新状态中和可拉动状态,且当前移动位置需大于开始位置,则设置容器跟随手指滚动;
  3. touchend触发时,判断刷新状态中和动画中,分两种情况:
    • 拉动距离超过刷新情况,则执行动画,刷新动作
    • 拉动距离没超过刷新情况,则返回原始状态
touchstart($event) {var vm= this;//判断是否允许下拉if (!vm.isPull && !vm.isLoading && vm._scrollWrap.scrollTop == vm.offsetTop) {vm.isPull= true;vm.startPos= $event.touches[0].pageY;};
},
touchmove($event) {var vm= this;vm.endPos= $event.touches[0].pageY;//是否能拉动if (!vm.isLoading && vm.isPull && vm.startPos<vm.endPos) {vm.distance= (vm.endPos- vm.startPos)*vm.modulus;var offsetLoading= vm._loadingWrap.offsetHeight;if (vm.distance >= offsetLoading) {vm.pullStatus = 'up'}else{vm.pullStatus = 'down'}vm.moveTransition(vm.$refs.scroll, vm.distance, 0);}
},
touchend($event) {var vm= this;var offsetLoading= vm._loadingWrap.offsetHeight;// vm.isPull= false;//加载中 或 移动距离小于0不能移动if (vm.isLoading || vm.distance<=0 || vm.isBack) {return false;}//拉动距离大于临界值if ( vm.distance>0 && vm.distance >= offsetLoading) {//执行刷新动作vm.pullTransition({dom: vm._scrollWrap,begin: offsetLoading,end: vm.distance,duration: 500});//后台刷新数据vm.refresh();}else{vm.isBack= true;// 返回back初始状态vm.pullTransition({dom: vm._scrollWrap,end: vm.distance,duration: 500,callback: vm.resetStatus});}
}
复制代码

下拉动画实现

采用css动画,则难以精准把握动画结束的时间。故采用RequestAnimationFrame实现动画,可监听到结束状态并处理回调。有关 requestAnimationFrame参考以下资料:

  • requestAnimationFrame
  • CSS3动画那么强,requestAnimationFrame还有毛线用?
/**
* [pullTransition 动画拉动]
* @param  {[type]} dom [元素]
* @param  {[type]} begin [起始值]
* @param  {[type]} end [结束值]
* @param  {[type]} duration [时间]
* @param  {[type]} callback [回调函数]
* @return {[type]}          [description]
*/
pullTransition(opt) {var vm= this;if (!opt.dom || !opt.end) {console.error('参数不足');return false;};var opt= {dom: opt.dom,currentTime: 0,begin: opt.begin? opt.begin: 0,end: opt.end,//相当一部分的浏览器的显示频率是16.7ms 约等于17duration: opt.duration? Math.ceil(opt.duration / 17) : 0,callback: opt.callback || false};var step= function() {//根据缓动算法取得值var value = opt.end-vm.easeInOut(opt.currentTime, opt.begin, opt.end-opt.begin, opt.duration)+opt.begin;opt.dom.style.transform= 'translate3d(0,'+value+'px,0)';opt.currentTime++;//判断是否到时间if (opt.currentTime <= opt.duration) {// 继续运动requestAnimationFrame(step);} else {// 动画结束if(opt.callback) opt.callback();} };step();
}
/**
* [Linear 缓动算法]
* @param {[type]} t [current time(当前时间)]
* @param {[type]} b [beginning value(初始值)]
* @param {[type]} c [change in value(变化量)]
* @param {[type]} d [duration(持续时间)]
*/
easeInOut(t, b, c, d) {if ((t /= d / 2) < 1) return c / 2 * t * t*t + b;return c / 2*((t -= 2) * t * t + 2) + b;      
}
复制代码

微信下拉显示网址处理

在微信打开一个页面时,在顶部用力往下拉的时候会出现如下图情况,对于下拉刷新来说体验比较差。我在网上搜索了下找到两种方式处理,供各位参考。本例子采用第一种方式,至于采用的依据目前还未深入比较,后续再深入调查。

  • 微信里面防止下拉"露底"组件
  • prevent-overscroll


至此,下拉刷新功能完成,任何意见和建议欢迎提出。

本文标签: 下拉刷新