官方文档:http://dev.dcloud.net.cn/mui/pullup/

一 mui原生下拉刷新及上拉加载

1 简述

为实现下拉刷新功能,大多数 H5 框架都是通过 DIV 模拟下拉回弹动画,在低端 android 手机上,DIV 动画经常出现卡顿现象(特别是图文列表的情况); mui 通过使用原生 webview 下拉刷新解决这个 DIV 动画的卡顿问题,并且拖动效果更加流畅。
但是,在wap网页中使用mui下拉刷新/上拉加载,只能使用DIV来实现mui的单 webview 模式/双 webview 模式,简而言之:单 webview 模式就是在同一个页面上完成加载;双 webview 模式就是在子页面完成拖动、加载列表整个流程,展示在父页面上(wap网页则是通过frame形式实现),此处推荐在wap网页中使用单webview模式。

2 实现流程

iOS平台的下拉刷新,使用的是 mui 封装的区域滚动组件, 为保证两个平台的 DOM 结构一致,内容页面需统一按照如下 DOM 结构构建:

  1. <!--下拉刷新容器-->
  2. <div id="refreshContainer" class="mui-content mui-scroll-wrapper">
  3. <div class="mui-scroll">
  4. <!--数据列表-->
  5. <ul class="mui-table-view mui-table-view-chevron">
  6. </ul>
  7. </div>
  8. </div>

其次,在JS中通过 mui.init 方法中 pullRefresh 参数配置下拉刷新各项参数,如下:

  1. mui.init({
  2. pullRefresh : {
  3. container:"#refreshContainer",//下拉刷新容器标识,querySelector能定位的css选择器均可,比如:id、.class等
  4. down : {
  5. height:50,//可选,默认50.触发下拉刷新拖动距离,
  6. auto: true,//可选,默认false.首次加载自动下拉刷新一次
  7. contentdown : "下拉可以刷新",//可选,在下拉可刷新状态时,下拉刷新控件上显示的标题内容
  8. contentover : "释放立即刷新",//可选,在释放可刷新状态时,下拉刷新控件上显示的标题内容
  9. contentrefresh : "正在刷新...",//可选,正在刷新状态时,下拉刷新控件上显示的标题内容
  10. callback :pullfresh-function //必选,刷新函数,根据具体业务来编写,比如通过ajax从服务器获取新数据;
  11. },
  12. up : {
  13. height:50,//可选.默认50.触发上拉加载拖动距离
  14. auto:true,//可选,默认false.自动上拉加载一次
  15. contentrefresh : "正在加载...",//可选,正在加载状态时,上拉加载控件上显示的标题内容
  16. contentnomore:'没有更多数据了',//可选,请求完毕若没有更多数据时显示的提醒内容;
  17. callback :pullfresh-function //必选,刷新函数,根据具体业务来编写,比如通过ajax从服务器获取新数据;
  18. }
  19. }
  20. });

3 加载的启动/禁用/结束触发

3-1.下拉刷新结束

在下拉刷新过程中,当获取新数据后,都需要执行 endPulldown 方法, 该方法的作用是关闭“正在刷新”的样式提示,内容区域回滚顶部位置,如下:

  1. //在上面定义的下拉刷新触发的回调函数
  2. function pullfresh-function() {
  3. //业务逻辑代码,比如通过ajax从服务器获取新数据;
  4. ......
  5. //注意,加载完新数据后,必须执行如下代码,注意:若为ajax请求,则需将如下代码放置在处理完ajax响应数据之后
  6. //没有更多内容了,endPulldown 传入true, 不再执行下拉刷新
  7. mui('#refreshContainer').pullRefresh().endPulldown();
  8. }

3-2.上拉加载结束/启用

和下拉刷新一样,上拉加载完新数据后,需要执行 endPullupToRefresh() 方法,结束转雪花进度条的“正在加载…”过程,enablePullupToRefresh(true|false) 传入true结束加载,为空或false时启用上拉加载。
如下:

  1. function pullfresh-function() {
  2. //业务逻辑代码,比如通过ajax从服务器获取新数据;
  3. ......
  4. //注意:
  5. //1、加载完新数据后,必须执行如下代码,true表示没有更多数据了:
  6. //2、若为ajax请求,则需将如下代码放置在处理完ajax响应数据之后
  7. //this.endPullupToRefresh(true|false);
  8. mui('#refreshContainer').pullRefresh().enablePullupToRefresh();
  9. }

3-3.上拉加载的重置

若部分业务中,有重新触发上拉加载的需求(比如当前类别已无更多数据,但切换到另外一个类别后,应支持继续上拉加载),此时调用 .refresh(true) 方法,可重置上拉加载控件,如下代码:

  1. //注意:refresh()中需传入true
  2. mui('#refreshContainer').pullRefresh().refresh(true);

3-4.上拉加载的禁用

在部分场景下希望禁用上拉加载,比如在列表数据过少时,不想显示“上拉显示更多”、“没有更多数据”的提示语,开发者可以通过调用 disablePullupToRefresh() 方法实现类似需求,代码如下:

  1. mui('#refreshContainer').pullRefresh().disablePullupToRefresh();

二 局部区域上拉加载

页面中存在多个模块,只在底部的模块中上拉刷新(触底时),加载更多数据

-HTML主要代码

  1. <div class="moduleWrap">
  2. <div class="module">
  3. <p class="title">大家都在看</p>
  4. <!-- 横向 -->
  5. <div class="hengWrap" id="allheng"></div>
  6. <!-- 间距 -->
  7. <div class="spacing"></div>
  8. <!-- 竖向 -->
  9. <!--下拉刷新容器-->
  10. <div id="pullrefresh">
  11. <!--数据列表-->
  12. <div class="shuWrap" id="allshu"></div>
  13. </div>
  14. </div>
  15. </div>

-js调用主要代码

  1. mui.init({
  2. pullRefresh: {
  3. container: "#pullrefresh", //下拉刷新容器标识,querySelector能定位的css选择器均可,比如:id、.class等
  4. up: {
  5. style:'circle',//必选,下拉刷新样式,目前支持原生5+ ‘circle’ 样式
  6. //color:'#2BD009', //可选,默认“#2BD009” 下拉刷新控件颜色
  7. height: 50, //可选.默认50.触发上拉加载拖动距离
  8. auto: true, //可选,默认false.自动上拉加载一次
  9. contentrefresh: "正在加载...", //可选,正在加载状态时,上拉加载控件上显示的标题内容
  10. contentnomore: '没有更多数据了', //可选,请求完毕若没有更多数据时显示的提醒内容;
  11. callback: pullupRefresh //必选,刷新函数,根据具体业务来编写,比如通过ajax从服务器获取新数据;
  12. }
  13. },
  14. gestureConfig: {
  15. doubletap: true //双击事件默认是关闭
  16. }
  17. });
  18. var totalnum
  19. ,countStop
  20. ,scrollNum =3
  21. ,count = 0;
  22. //初始化获取“大家都在看”的书籍长度
  23. mainapi('promote', {id:1004}, function(res) {
  24. totalnum =res.data.length;
  25. });
  26. /**
  27. * 上拉加载具体业务实现
  28. */
  29. function pullupRefresh() {
  30. console.log('totalnum:'+totalnum);
  31. setTimeout(function() {
  32. countStop = totalnum ? parseInt(totalnum / 3) : 1;
  33. console.log("countStop:" + countStop +"num:" + count+" totalnum:"+totalnum);
  34. scrollNum += 3;
  35. everyData2();
  36. mui('#pullrefresh').pullRefresh().endPullupToRefresh((++count > countStop));
  37. //参数为true代表没有更多数据了。
  38. }, 1000);
  39. }
  40. if(mui.os.plus) {
  41. mui.plusReady(function() {
  42. setTimeout(function() {
  43. mui('#pullrefresh').pullRefresh().pullupLoading();
  44. }, 100);
  45. });
  46. } else {
  47. mui.ready(function() {
  48. mui('#pullrefresh').pullRefresh().pullupLoading();
  49. });
  50. }
  51. function everyData2() {
  52. var obj4 = {
  53. id: 1004,
  54. num: scrollNum
  55. }
  56. mainapi('promote', obj4, function(res) {
  57. var everbodyData = res.data;
  58. creatHengWrap("", "#allshu", everbodyData, 3);
  59. });
  60. }

三 同一页面中执行多个不同容器的下拉/上拉加载

截止到目前(Mui V3.7.2版本),mui的下拉/上拉加载仍是在同一页面中只支持单一页面的加载刷新执行,mui示例中给出了tab选项卡切换和多个相同上拉下拉加载的方案实例(点击查看)。

1 源码改造

综合网友分享经验,目前实现此需求,需要对mui.js的源码进行少量的修改,详细可参考mui.read.js查看2957行至3023行结合mui.js对比。修改逻辑大致如下(暂时不必深究):
mui.read.js
1-1.将源码中获取的pullRefresh对象(单个)改写为对象数组
1-2.使用for循环将对象数组中的元素赋值并执行定义的函数

2 js中调用

2-1.初始化时传入多个对象

mui初始化时,可传入一个或多个对象,分别定义样式及回调函数

  1. /*初始化加载内容*/
  2. mui.init({
  3. pullRefresh: [{
  4. container: '#offCanvasContentScroll',
  5. down: {
  6. style:'circle',
  7. callback: pulldownRefresh
  8. },
  9. up: {
  10. style:'circle',
  11. height:0,
  12. contentrefresh: '上拉显示下一章...',
  13. contentnomore:'即将进入下一章',
  14. callback: pullupRefresh
  15. }
  16. },{
  17. container: '#offCanvasSideScroll',
  18. up: {
  19. style:'circle',//必选,下拉刷新样式,目前支持原生5+ ‘circle’ 样式
  20. //color:'#2BD009', //可选,默认“#2BD009” 下拉刷新控件颜色
  21. //height: 50, //可选.默认50.触发上拉加载拖动距离
  22. auto: true, //可选,默认false.自动上拉加载一次
  23. contentrefresh: "正在加载...", //可选,正在加载状态时,上拉加载控件上显示的标题内容
  24. contentnomore: '没有更多数据了', //可选,请求完毕若没有更多数据时显示的提醒内容;
  25. callback: pullupChapter //必选,刷新函数,根据具体业务来编写,比如通过ajax从服务器获取新数据;
  26. }
  27. }]
  28. });

2-2.分别定义回调函数

  1. //上拉加载下一章
  2. function pullupRefresh() {
  3. //mui('#offCanvasContentScroll').pullRefresh().endPullupToRefresh();
  4. count2++;
  5. setTimeout(function() {
  6. //mui('#offCanvasContentScroll').pullRefresh().endPullupToRefresh(); //参数为true代表没有更多数据了。(count === 2)
  7. mui('#offCanvasContentScroll').pullRefresh().disablePullupToRefresh();
  8. //mui('#offCanvasContentScroll').pullRefresh().endPullupToRefresh();
  9. console.log(count2);
  10. if(count2 > 2){
  11. next();
  12. }else{
  13. return true;
  14. }
  15. }, 1500);
  16. }
  17. //下拉加载上一章
  18. function pulldownRefresh() {
  19. setTimeout(function() {
  20. prev();
  21. mui('#offCanvasContentScroll').pullRefresh().endPulldownToRefresh();
  22. }, 1500);
  23. }
  24. //上拉加载目录
  25. function pullupChapter() {
  26. setTimeout(function() {
  27. countStop = totalnum ? parseInt(totalnum / 50) : 1;
  28. num += 50;
  29. chapterList();
  30. mui('#offCanvasSideScroll').pullRefresh().endPullupToRefresh((++count > countStop)); //参数为true代表没有更多数据了。
  31. }, 1000);
  32. }

2-3.定义执行函数

定义回调函数中执行的函数,完毕

  1. function next(){
  2. //跳转下一章
  3. }
  4. function prev(){
  5. //跳转上一章
  6. }
  7. function chapterList(){
  8. //ajax请求目录数据,绑定拼接
  9. }

四 同一页面中多次调用同一个上拉加载

备注:在切换调用上拉加载回调函数前,需要先调用 .refresh(true) 重置上拉加载控件

使用场景:比如在tab选项卡场景下,当前类别上拉加载已无更多数据,但点击切换到另外一个类别后,应支持继续上拉加载(此时需要重置上拉加载)

代码示例:仅为单个场景使用实例,并非所有的实现都需要按照这个逻辑流程

  1. //点击不同tab切换分类
  2. function cateTab(val) {
  3. //执行函数……
  4. //调用了ajax加载方法
  5. everyData2();
  6. }
  7. //在定义上拉加载回调函数中,也会调用ajax请求方法
  8. function pullupRefresh() {
  9. setTimeout(function() {
  10. countStop = totalnum ? parseInt(totalnum / 6) : 1;
  11. //调用了ajax加载方法
  12. everyData2();
  13. scrollNum += 6;
  14. mui('#pullrefresh').pullRefresh().endPullupToRefresh((++count > countStop)); //参数为true代表没有更多数据了。(++count > countStop)
  15. }, 1000);
  16. }
  17. //因此在ajax加载方法函数中,调用.refresh(true)重置
  18. function everyData2() {
  19. //console.log('执行在这里');
  20. //mui('#bookList')[0].innerHTML = '';
  21. mui('#pullrefresh').pullRefresh().refresh(true);
  22. //mui.ajax()
  23. }