iScroll-5拉动刷新(pull-to-refresh)功能实现与iScroll-4上拉刷新的一点改进

来源:网络    编辑:admin

近来在学习移动设备的应用开发,接触了jQuery mobile,在网上查阅相关资料时发现一个叫”iScroll“的小插件。其实这个iScroll插件跟jQuery mobile没有多大关系,并不是基于jQuery mobile类库开发的js插件,是一个独立的js插件,使用它时不必预先引用jquery或jquery mobile类库。关于iScroll的详细介绍可以去它的官网了解或者去GitHub(https://github.com/cubiq/iscroll/)下载它的源码学习。iScroll现在已经更新为iScroll-5,但并没有加入太多新的功能,只是对前一个版本iScroll-4进行重构优化与修复,而且官方消息说不再对iScroll-4进行维护和技术支持,建议使用新版本。官方说法如下:



iScroll-5与iScroll-4的差别还挺大的,首先在声明定义上写法就不一样了。













iScroll-4:iScroll-5:


var myScroll = new iScroll("wrapper", {
    useTransition: true,
    topOffset: pullDownOffset,
    onRefresh: function () {
        ...
    },
   onScrollStart: function () { 
     ...
   },
   onScrollMove: function () { 
     ...
   },
   onScrollEnd: function () { 
     ...
   }
   
   .... 
});


 



var myScroll = new IScroll("#wrapper", {
    mouseWheel: true,
    scrollbars: true,
    startY:-pullDownOffset
    ...
});

//Event: scroll start
myScroll.on("scrollStart", function() {
    ...
});
    
//Event: scroll
myScroll.on("scroll", function(){
    ...
});
    
//Event: scrollEnd
myScroll.on("scrollEnd", function() {
    ...
});

//Event: refresh
myScroll.on("refresh", function() {
    ...
});

...


 


 


从上面两者的示例代码对比,以前的声明定义是new iScroll("wrapper"...),现在变为new IScroll("#wrapper"...),类名变为大写I开头了,容器的Id要加上前缀#,某些参数名称改变了(以前的topOffset变为startY和startX),关键是事件(event)不再是从options参数中指定,而是用on去注册等等。


还有一个重大的不同是,iScroll-5按照功能点不同自身又划分为不同的版本,官方划分如下:



还有其他的差异就不再逐个列出了,大家可以到官网去了解。


其实iScroll之所以吸引我,主要是在iScroll-4中的demo里面有一个叫”pull-to-refresh“的示例,也就是我们说拉动更新,包括列表内容的下拉和上拉更新。这个功能在触摸的移动应用上经常用到,可以不夸张的说是必不可少的。但这个重要的示例在新版iScroll-5的demo中却找不到了。不知什么原因作者将它去掉了(据说iScroll-4的pull-to-refresh这个示例并不是作者的杰作),我在网上找了很久都没发现有关于iScroll-5官方的pull-to-refresh示例,个别实现的例子倒也是有一些,但效果都不是很令人满意。为了加深和巩固对iScroll的学习,本人就参考iScroll-4的pull-to-refresh示例来实现iScroll-5的拉动刷新功能,同时也对iScroll-4的pull-to-refresh示例根据个人需求进行了一点改进。


首先给出iScroll-4的pull-to-refresh示例改动后的代码:



  1 <script type="text/javascript">
  2 
  3 var myScroll,
  4     pullDownEl, pullDownOffset,
  5     pullUpEl, pullUpOffset, _maxScrollY;
  6 var generatedCount = 0;
  7 
  8 function pullDownAction () {
  9     setTimeout(function () {    // <-- Simulate network congestion, remove setTimeout from production!
 10         var el, li, i;
 11         el = document.getElementById("thelist");
 12 
 13         for (i=0; i<3; i++) {
 14             li = document.createElement("li");
 15             li.innerHTML = "(Pull down) Generated row " + (++generatedCount);//Firefox  does not suppose innerText, use innerHTML instead.
 16             el.insertBefore(li, el.childNodes[0]);
 17         }
 18         
 19         myScroll.refresh();        // Remember to refresh when contents are loaded (ie: on ajax completion)
 20     }, 1000);    // <-- Simulate network congestion, remove setTimeout from production!
 21 }
 22 
 23 function pullUpAction () {
 24     setTimeout(function () {    // <-- Simulate network congestion, remove setTimeout from production!
 25         var el, li, i;
 26         el = document.getElementById("thelist");
 27 
 28         for (i=0; i<3; i++) {
 29             li = document.createElement("li");
 30             li.innerHTML = "(Pull up) Generated row " + (++generatedCount);//Firefox  does not suppose innerText, use innerHTML instead.
 31             el.appendChild(li, el.childNodes[0]);
 32         }
 33         
 34         myScroll.refresh();        // Remember to refresh when contents are loaded (ie: on ajax completion)
 35     }, 1000);    // <-- Simulate network congestion, remove setTimeout from production!
 36 }
 37 
 38 function loaded() {
 39     pullDownEl = document.getElementById("pullDown");
 40     pullDownOffset = pullDownEl.offsetHeight;
 41     pullUpEl = document.getElementById("pullUp");    
 42     pullUpOffset = pullUpEl.offsetHeight;
 43     
 44     
 45     myScroll = new iScroll("wrapper", {
 46         useTransition: true,
 47         topOffset: pullDownOffset,
 48         onRefresh: function () {
 49             console.log("maxScrollY-0:"+this.maxScrollY);
 50             _maxScrollY = this.maxScrollY = this.maxScrollY + pullUpOffset;
 51             console.log("maxScrollY-1:"+this.maxScrollY);
 52             if (pullDownEl.className.match("loading")) {
 53                 pullDownEl.className = "";
 54                 pullDownEl.querySelector(".pullDownLabel").innerHTML = "Pull down to refresh...";
 55             } else if (pullUpEl.className.match("loading")) {
 56                 pullUpEl.className = "";
 57                 pullUpEl.querySelector(".pullUpLabel").innerHTML = "Pull up to load more...";
 58                 this.scrollTo(0,this.maxScrollY,0);
 59             }
 60         },
 61         onScrollMove: function () {
 62             console.log("maxScrollY-3:"+this.maxScrollY);
 63             if (this.y > 5 && !pullDownEl.className.match("flip")) {
 64                 pullDownEl.className = "flip";
 65                 pullDownEl.querySelector(".pullDownLabel").innerHTML = "Release to refresh...";
 66                 this.minScrollY = 0;
 67             } else if (this.y < 5 && pullDownEl.className.match("flip")) {
 68                 pullDownEl.className = "";
 69                 pullDownEl.querySelector(".pullDownLabel").innerHTML = "Pull down to refresh...";
 70                 this.minScrollY = -pullDownOffset;
 71             } else if (this.y <= (_maxScrollY - pullUpOffset) && !pullUpEl.className.match("flip")) {
 72                 pullUpEl.className = "flip";
 73                 pullUpEl.querySelector(".pullUpLabel").innerHTML = "Release to refresh...";
 74                 this.maxScrollY = this.maxScrollY - pullUpOffset;
 75             } else if (this.y > (_maxScrollY - pullUpOffset) && pullUpEl.className.match("flip")) {
 76                 pullUpEl.className = "";
 77                 pullUpEl.querySelector(".pullUpLabel").innerHTML = "Pull up to load more...";
 78                 this.maxScrollY = this.maxScrollY + pullUpOffset;
 79             }
 80         },
 81         onScrollEnd: function () {
 82             if (pullDownEl.className.match("flip")) {
 83                 pullDownEl.className = "loading";
 84                 pullDownEl.querySelector(".pullDownLabel").innerHTML = "Loading...";                
 85                 console.log("pull down---scroll end");
 86                 pullDownAction();    // Execute custom function (ajax call?)
 87             } else if (pullUpEl.className.match("flip")) {
 88                 pullUpEl.className = "loading";
 89                 pullUpEl.querySelector(".pullUpLabel").innerHTML = "Loading...";
 90                 console.log("pull up---scroll end");                
 91                 pullUpAction();    // Execute custom function (ajax call?)
 92             }
 93         }
 94     });
 95     
 96     
 97     setTimeout(function () { document.getElementById("wrapper").style.left = "0"; }, 800);
 98 }
 99 
100 document.addEventListener("touchmove", function (e) { e.preventDefault(); }, false);
101 
102 document.addEventListener("DOMContentLoaded", function () { setTimeout(loaded, 200); }, false);
103 </script>


上面代码高亮标注(黄色底色)的地方是主要的改动点,对于第15,30行标注的innerHTML原来例子是innerText,但我发现在firefox运行后新增的li会显示不了内容(应该是firebox不支持innerText),改为innerHTML后就正常显示了。其他处的改动主要是针对maxScrollY这个变量,这样改主要是为了让列表内容滚动到底部时上拉前不显示提示栏。













iScroll-4 示例改动前:iScroll-4 示例改动后:

 


 


 


 


 


 


 


 


 


 


 


 


 


 


 


 


 


 


 


 


下面参照iScroll-4改动后的push-to-refresh示例来实现iScroll-5的拉动刷新功能。使用iScroll-5来实现的话,要引用的js类库是iScroll-5细分后的iscroll-probe.js,按照前面的划分介绍,此细分版本主要是为了探查当前滚动位置(x,y)。在实现过程中我发现类库有一小处源码是需要改动的,主要是解决鼠标滑轮向顶部滚动时,不显示下拉提示栏(这个问题在iScroll-4下是不存在的,应该跟iScroll-5去掉了minScrollY这个变量有关),我们希望在下拉时才会出现提示栏。



解决办法其实也不复杂,只需改动一下iscroll-probe.js文件里面的第1122行处的一小段代码。如下图:



之所以这样修改,主要是参考iScroll-4里面的源码。如下图:




好,源文件iscroll-probe.js的修改就完成了,下面给出iScroll-5拉动刷新功能的页面js代码:



  1 <script type="text/javascript">
  2 
  3 var myScroll, 
  4     pullDownEl, pullDownOffset,
  5     pullUpEl, pullUpOffset, _maxScrollY;
  6     
  7 var generatedCount = 0;
  8 
  9 function pullDownAction(){
 10         setTimeout(function () {    // <-- Simulate network congestion, remove setTimeout from production!
 11             var el, li, i;
 12             el = document.querySelector("#scroller ul");
 13     
 14             for (i=0; i<3; i++) {
 15                 li = document.createElement("li");
 16                 li.innerHTML = "(Pull down) Generated row " + (++generatedCount);//Firefox  does not suppose innerText, use innerHTML instead.
 17                 el.insertBefore(li, el.childNodes[0]);
 18             }
 19             if(myScroll){
 20                 myScroll.refresh();        // Remember to refresh when contents are loaded (ie: on ajax completion)
 21             }
 22         }, 1000);    // <-- Simulate network congestion, remove setTimeout from production!
 23 }
 24 
 25 function pullUpAction () {
 26     setTimeout(function () {    // <-- Simulate network congestion, remove setTimeout from production!
 27         var el, li, i;
 28         el = document.querySelector("#scroller ul");
 29 
 30         for (i=0; i<3; i++) {
 31             li = document.createElement("li");
 32             li.innerHTML = "(Pull up) Generated row " + (++generatedCount);//Firefox  does not suppose innerText, use innerHTML instead.
 33             el.appendChild(li, el.childNodes[0]);
 34         }
 35         if(myScroll){
 36             myScroll.refresh();        // Remember to refresh when contents are loaded (ie: on ajax completion)
 37         }
 38     }, 1000);    // <-- Simulate network congestion, remove setTimeout from production!
 39 }
 40 
 41 function loaded() {
 42     pullDownEl = document.querySelector("#pullDown");
 43     if (pullDownEl) {
 44         pullDownOffset = pullDownEl.offsetHeight;
 45     } else {
 46         pullDownOffset = 0;
 47     }
 48     pullUpEl = document.querySelector("#pullUp");    
 49     if (pullUpEl) {
 50         pullUpOffset = pullUpEl.offsetHeight;
 51     } else {
 52         pullUpOffset = 0;
 53     }
 54     
 55     console.log("pullDownOffset:"+pullDownOffset);
 56     console.log("pullUpOffset:"+pullUpOffset);
 57     
 58     //Options of IScroll
 59     var myOptions = {
 60             mouseWheel: true,
 61             scrollbars: true,
 62             fadeScrollbars: true,
 63             probeType:1,
 64             startY:-pullDownOffset
 65         };
 66     myScroll = new IScroll("#wrapper",myOptions);
 67     console.log("maxScrollY-1:"+myScroll.maxScrollY);
 68     _maxScrollY = myScroll.maxScrollY = myScroll.maxScrollY + pullUpOffset;
 69     console.log("maxScrollY-2:"+myScroll.maxScrollY);
 70     
 71     var isScrolling = false;
 72     
 73     //Event: scrollStart
 74     myScroll.on("scrollStart", function() {
 75         if(this.y==this.startY){
 76             isScrolling = true;
 77         }
 78         console.log("start-y:"+this.y);
 79     });
 80     
 81     //Event: scroll
 82     myScroll.on("scroll", function(){
 83         if (this.y >= 5 && pullDownEl && !pullDownEl.className.match("flip")) {
 84             pullDownEl.className = "flip";
 85             pullDownEl.querySelector(".pullDownLabel").innerHTML = "Release to refresh";
 86             //this.minScrollY = 0;
 87         } else if (this.y < 5  && pullDownEl && pullDownEl.className.match("flip")) {
 88             pullDownEl.className = "";
 89             pullDownEl.querySelector(".pullDownLabel").innerHTML = "Pull down to refresh";
 90             //this.minScrollY = -pullDownOffset;
 91         }else if (this.y <= (_maxScrollY - pullUpOffset) && pullUpEl && !pullUpEl.className.match("flip")) {
 92             pullUpEl.className = "flip";
 93             pullUpEl.querySelector(".pullUpLabel").innerHTML = "Release to refresh";
 94             //this.maxScrollY = this.maxScrollY;
 95             this.maxScrollY = this.maxScrollY - pullUpOffset;
 96         } else if (this.y > (_maxScrollY - pullUpOffset) && pullUpEl && pullUpEl.className.match("flip")) {
 97             pullUpEl.className = "";
 98             pullUpEl.querySelector(".pullUpLabel").innerHTML = "Pull up to load more";
 99             //this.maxScrollY = pullUpOffset;
100             this.maxScrollY = this.maxScrollY + pullUpOffset;
101         }
102                     
103         console.log("y:"+this.y);
104     });
105     
106     //Event: scrollEnd
107     myScroll.on("scrollEnd", function() {
108         console.log("scroll end"); 
109         console.log("directionY:"+this.directionY);
110         console.log("y1:"+this.y);
111         console.log("maxScrollY-3:"+this.maxScrollY);
112         if (pullDownEl && !pullDownEl.className.match("flip") && this.y > this.options.startY) {
113             console.log("resume"); 
114             this.scrollTo(0, this.options.startY,800);
115           }
116         else if (pullDownEl && pullDownEl.className.match("flip")){
117                 pullDownEl.className = "loading";
118                 pullDownEl.querySelector(".pullDownLabel").innerHTML = "Loading...";                
119                 // Execute custom function (ajax call?)
120                 if (isScrolling) {
121                     console.log("before pull down action:"+this.y); 
122                     pullDownAction();
123                       console.log("after pull down action:"+this.y); 
124                   }
125         }
126         else if (pullUpEl && pullUpEl.className.match("flip")) {
127                 console.log("pull up loading"); 
128                 pullUpEl.className = "loading";
129                 pullUpEl.querySelector(".pullUpLabel").innerHTML = "Loading...";    
130                 // Execute custom function (ajax call?)
131                 if (isScrolling) {            
132                     console.log("before pull up action:"+this.y); 
133                     pullUpAction();    
134                     console.log("after pull up action:"+this.y); 
135                 }
136         }
137         isScrolling = false;
138     });
139     
140     //Event: refresh
141     myScroll.on("refresh", function() {
142           
143          console.log("maxScrollY-4:"+this.maxScrollY);
144          _maxScrollY = this.maxScrollY = this.maxScrollY+pullUpOffset;
145          console.log("maxScrollY-5:"+this.maxScrollY);
146          
147          if (pullDownEl  && pullDownEl.className.match("loading")) {
148                 pullDownEl.className = "";
149                 pullDownEl.querySelector(".pullDownLabel").innerHTML = "Pull down to refresh";
150                 this.scrollTo(0,this.options.startY,0);
151          } else if (pullUpEl && pullUpEl.className.match("loading")) {
152                 pullUpEl.className = "";
153                 pullUpEl.querySelector(".pullUpLabel").innerHTML = "Pull up to load more";
154                 this.scrollTo(0,this.maxScrollY,0);
155          }
156          
157          console.log("refresh finished!"); 
158     });
159     
160     setTimeout(function () { document.getElementById("wrapper").style.left = "0"; }, 500);
161     
162 }
163 
164 document.addEventListener("touchmove", function (e) { e.preventDefault(); }, false);
165 
166 </script>


运行效果:




















 iScroll-4:
 



















 iScroll-5:

后话:按照官网的介绍iScroll-5比iScroll-4更快,性能更好。但在上面的拉动刷新的示例中,iScroll-5在firefox中运行时比iScroll-4要占用更多的CPU,感觉iScroll-4要流畅得多,但仅限于拉动功能的比较,至于iScroll的其他功能没有测试对比过,所以也不敢以偏概全地断言说iScroll-5的性能就比上iScroll-4。有兴趣的朋友可以去测试一下,测完后给我分享一下结果,谢谢!

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值