如果你用vue弄移动端的页面,那么下拉刷新还是比较常见的场景,下面来研究如何写一个下拉刷新的组件(先上图);
由于节省大家的时间,样式就不贴出来了。
html结构也不必介绍了,直接看代码吧-.-
<transition>
<div class="refresh-wrapper" ref="refresh">
<div class="refresh-inner">
<div class="refresh-pull" v-show="state==='pull'">
<span>下拉刷新-.-</span>
</div>
<div class="refresh-loading" v-show="state==='loading'">
<span>刷新中...~.~</span>
</div>
<div class="refresh-end" v-show="state==='end'">
<span>刷新完成!^.^</span>
</div>
</div>
</div>
</transition>
核心思路及步骤
- 给
document
绑定touch
事件
document.addEventListener('touchstart',this.touchStart,false);
document.addEventListener('touchmove',this.touchMove,false);
document.body.addEventListener('touchend',this.touchEnd,false);
-
touchStart
细节
2.1 判断状态,这是为了防止在刷新时多次触发。可以定义一个变量保存状态,状态值为pull, loading, end
;
2.2 记录开始的位置,Y轴的就可以了;
2.3 获取当前touch
的对象? 虽然我们已经把事件绑定在document
上了,但是在有局部滚动的时候,那么向下滑动的时候就会有冲突,这个时候可以获取到当前touch
的对象,后面做处理;
touchStart(e){
if(this.state === 'loading') return;
this.startY = e.touches[0].clientY;
this.getTouchTarget(e.target);
}
getTouchTarget(elm){
let currentNode = elm;
while(currentNode && currentNode.tagName !== "HTML" &&
currentNode.tagName !== "BODY" && currentNode.nodeType === 1){
let overflowY = window.getComputedStyle(currentNode).overflowY;
if(overflowY === "scroll" || overflowY === "auto"){
this.currentNode = currentNode;
this.firstNode = currentNode.firstElementChild; //记录局部滚动的第一个子元素
break;
}
currentNode = currentNode.parentNode;
}
}
-
touchMove
细节
3.1 判断当前滑动的区域是否局部滚动,如果是,通过判断父元素和子元素的getBoundingClientRect().top
的差值是否小于0来判断是否滚动到顶部
3.2 判断一些其他的条件
3.3 记录滑动的距离
3.4 改变视图
touchMove(e){
let firstTop=0, currentTop=0;
if(this.firstNode){
firstTop = this.firstNode.getBoundingClientRect().top;
currentTop = this.currentNode.getBoundingClientRect().top;
}
let range = (e.touches[0].clientY - this.startY);
if( document.documentElement.scrollTop>0 || this.state === 'loading' || firstTop-currentTop <0 || range<0) return;
range = range*0.75 > this.maxRange? this.maxRange : range;
this.translate = range;
this.changeView();
}
changeView(){
//这里针对transfrom对fixed定位的bug做的降级处理
if(this.isFixed){
this.$refs.refresh.style.transform=`translate3d(0,${this.translate}px,0)`;
}else{
document.body.style.transform = `translate3d(0,${this.translate}px,0)`;
}
}
-
touchEnd
细节
4.1 判断状态
4.2 判断滑动距离是否到可刷新距离,如果是,调用刷新api
4.3 改变视图
touchEnd(e){
if(this.state === 'loading') return;
if(this.translate && this.translate >= this.maxRange){
this.translate = this.maxRange/2;
this.refresh();
}else{
this.translate = 0;
}
this.rotate = 0;
this.changeView();
}
refresh(){
this.state = 'loading';
console.log('更新中...');
this.$emit('refresh'); //父组件监听refresh方法,并在异步回调中调用子组件的refreshEnd方法,可通过this.$refs.名称.refreshEnd()方法调用
}
refreshEnd(){
let _this = this;
this.state = 'end';
setTimeout(()=>{
_this.translate = 0;
_this.changeView();
},1000);
setTimeout(()=>{
_this.state = 'pull';
},1300)
console.log('更新完成...');
}
注意
1.如果有fixed布局,要传isFixed='true',否则会有bug。关于transform 与fixed的bug,可以参考这里
2. 不建议用在过于复杂的布局,可能有未知bug -.-
用vue写一个仿app下拉刷新的组件的更多相关文章
-
用vue写一个仿简书的轮播图
原文地址:用vue写一个仿简书的轮播图 先展示最终效果: Vue的理念是以数据驱动视图,所以拒绝通过改变元素的margin-top来实现滚动效果.写好css样式,只需改变每张图片的class即可实现轮 ...
-
基于PtrFrameLayout实现自定义仿京东下拉刷新控件
前言 最近基于项目需要,使用PtrFrameLayout框架实现了自定义的下拉刷新控件,大体效果类似于京东APP的下拉刷新动态效果.在这里和大家分享一下具体的思路和需要注意的地方,以便帮助有类似开发和 ...
-
高仿IOS下拉刷新的粘虫效果
最近看需要做一款下拉刷新的效果,由于需要和Ios界面保持一致,所以这用安卓的方式实现了ios下的下拉刷新的粘虫效果. 最新的安卓手机版本的QQ也有这种类似的效果,就是拖动未读信息的那个红色圆圈,拖动近 ...
-
vue实现网络图片瀑布流 + 下拉刷新 + 上拉加载更多
一.思路分析和效果图 用vue来实现一个瀑布流效果,加载网络图片,同时有下拉刷新和上拉加载更多功能效果.然后针对这几个效果的实现,捋下思路: 根据加载数据的顺序,依次追加标签展示效果: 选择哪种方式实 ...
-
Android自定义控件之仿美团下拉刷新
美团的下拉刷新分为三个状态: 第一个状态为下拉刷新状态(pull to refresh),在这个状态下是一个绿色的椭圆随着下拉的距离动态改变其大小. 第二个部分为放开刷新状态(release to r ...
-
IOS怎么实现一个UITableView的下拉刷新
採用的EGORefreshTableHeaderView来实现: 在Controller上实现EGORefreshTableHeaderDelegate的delegate @property(nona ...
-
打造通用的Android下拉刷新组件(适用于ListView、GridView等各类View)
前言 近期在做项目时,使用了一个开源的下拉刷新ListView组件.极其的不稳定,bug还多.稳定的组件又写得太复杂了,jar包较大.在我的一篇博客中也讲述过下拉刷新的实现,即Android打造(Li ...
-
Android仿苹果版QQ下拉刷新实现(一) ——打造简单平滑的通用下拉刷新控件
前言: 忙完了结婚乐APP的开发,终于可以花一定的时间放在博客上了.好了,废话不多说,今天我们要带来的效果是苹果版本的QQ下拉刷新.首先看一下目标效果以及demo效果: 因为此效果实现的步骤 ...
-
如何写一套下拉刷新的控件?《MJRefresh原理浅析》(附Demo下载地址)
相信大家有很多人在做项目的时候都在使用MJRefresh 控件来实现下拉刷新的功能: MJRefresh经过不断的重构与更新迭代,现在不管是功能上还是代码结构上都是相当不错的,都是很值我们去学习的. ...
随机推荐
-
编码Q&;A
Q:什么是编码? A:由于计算机中所有数据都是以二进制存在,那么为了存储数字,字母,各种符号和文字,计算机必须用一套映射系统来对应.比如我在某台计算机上规定,用00010001这个二进制数表示字母a, ...
-
hdu 2629 Identity Card (字符串解析模拟题)
这题是一个字符串模拟水题,给12级学弟学妹们找找自信的,嘿嘿; 题目意思就是要你讲身份证的上的省份和生日解析出来输出就可以了: http://acm.hdu.edu.cn/showproblem.ph ...
-
quartz 的job中获取到applicationContext
第一步: 定义SchedulerFactoryBean的applicationContextSchedulerContextKey <bean name="scheduler" ...
-
DIY Ruby CPU 分析——Part III
[编者按]作者 Emil Soman,Rubyist,除此之外竟然同时也是艺术家,吉他手,Garden City RubyConf 组织者.本文是 DIY Ruby CPU Profiling 的第二 ...
-
[原创]leet code - path sum
; ; ; } } ; }};
-
[ACM] poj 1258 Agri-Net (最小生成树)
Agri-Net Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 37131 Accepted: 14998 Descri ...
-
hadoop记录-hive常见设置
分区表 set hive.exec.dynamic.partition=true; set hive.exec.dynamic.partition.mode=nonstrict;create tabl ...
-
JDK1.8 HashMap--treeifyBin()方法
/*树形化*/ final void treeifyBin(Node<K,V>[] tab, int hash) { int n, index; Node<K,V> e;// ...
-
《统计学习方法》笔记(8):AdaBoost算法
AdaBoost是最有代表性的提升算法之一.其基本思想可以表述为:多个专家的综合判断,要优于任意一个专家的判断. 1.什么是提升算法? "装袋"(bagging)和"提升 ...
-
linux 将一个文件分解成多个不同名文件
1.通过c直接实现 #include <stdio.h> #include <stdlib.h> #include <sys/types.h> #include & ...