随时随地阅读更多技术实战干货,获取项目源码、学习资料,请关注源代码社区公众号(ydmsq666)
最近在一个项目中有用到下拉刷新和上拉加载更多的功能,选择了mui框架,研究了下,使用起来还是蛮简单的,不过也遇到一些坑,这里把最终整理出来的分享下,大多数 H5 框架都是通过 DIV 模拟下拉回弹动画,在低端 android 手机上,DIV 动画经常出现卡顿现象(特别是图文列表的情况); 而mui 通过使用原生 webview 下拉刷新解决这个 DIV 动画的卡顿问题,并且拖动效果更加流畅;mui提供两种模式的下拉刷新,以适用不同场景:第一种是单webview模式,另一种是双webview模式
1、单webview模式下,触发的是原生下拉刷新控件,而整个webview
位置不会发生变化,所以不会在拖动过程中发生DOM重绘,当控件拖动到一定位置触发动态加载数据以及刷新操作。此模式下拉刷新,相比双webview 模式,不创建额外 webview,性能更优。
- 优点:
- 性能更优,体现在两点:
- 相比双webview,不创建额外子 webview 性能消耗更少
- 下拉拖动过程中不会发生重绘,也减少了性能消耗
- 性能更优,体现在两点:
- 缺点:
- 目前仅支持‘cricle’样式以及该样式的颜色自定义
2、双webview模式下的下拉刷新,创建一个子 webview 添加列表;拖动时,拖动的是一个完整的 webview,避免了类似 DIV 拖动流畅度不好的问题,回弹动画使用原生动画;在 iOS 平台,H5 的动画已经比较流畅,故依然使用 H5 方案。两个平台实现虽有差异,但 mui 经过封装,可使用一套代码实现下拉刷新。
使用时,需要在主页面创建子页面
mui.init({
subpages:[{
url:pullrefresh-subpage-url,//下拉刷新内容页面地址
id:pullrefresh-subpage-id,//内容页面标志
styles:{
top:subpage-top-position,//内容页面顶部位置,需根据实际页面布局计算,若使用标准mui导航,顶部默认为48px;
.....//其它参数定义
}
}]
});
- 优点:
- 可自定义下拉刷新样式,更改文字等等.
- 缺点:
- 相比单 webview,性能消耗更大,不过都比 div 模式的要好用
- DOM结构需要统一配置
在双webview模式,有个特别好处就是还可以根据实际需求在父页面给mui-content设置top属性
.mui-bar-nav ~ .mui-content .mui-pull-top-pocket{
top: 180px !important;
}
其它设置差不多,下面就以单webview模式举一个实例:
首先需要在页面引用这个js,这个是基本的就不多说了,然后要进行初始化:
mui.init({
swipeBack : true,//右滑关闭
pullRefresh : {
container : '#pullrefresh',//下拉刷新容器标识,querySelector能定位的css选择器均可,比如:id、.class等
down : {
height : 50,//可选,默认50.触发下拉刷新拖动距离,
range : 100, //可选 默认100px,控件可下拉拖拽的范围
offset : 30, //可选 默认0px,下拉刷新控件的起始位置
color : '#2BD009', //可选,默认“#2BD009” 下拉刷新控件颜色
style : 'circle',//可选,下拉刷新样式,目前支持原生5+ ‘circle’ 样式
auto : false,//可选,默认false.自动下拉刷新一次
contentdown : "下拉可以刷新",//可选,在下拉可刷新状态时,下拉刷新控件上显示的标题内容
contentover : "释放立即刷新",//可选,在释放可刷新状态时,下拉刷新控件上显示的标题内容
contentrefresh : "正在刷新...",//可选,正在刷新状态时,下拉刷新控件上显示的标题内容
callback : pulldownRefresh//必选,刷新函数,根据具体业务来编写,比如通过ajax从服务器获取新数据
},
up : {
height : 50,//可选.默认50.触发上拉加载拖动距离
auto : false,//可选,默认false.自动上拉加载一次
contentrefresh : "正在加载...",//可选,正在加载状态时,上拉加载控件上显示的标题内容
contentnomore : '没有更多数据了',//可选,请求完毕若没有更多数据时显示的提醒内容
callback : pullupRefresh//必选,刷新函数,根据具体业务来编写,比如通过ajax从服务器获取新数据
}
}
});
上拉和下拉配置都在里面,都有详细注释,初始化完成就可以上拉和下拉了,这里有两个必须的回调方法,用来处理具体业务逻辑,每个人具体需求不一样,这里就以自己的一个需求作为示例:
// 下拉刷新具体业务实现
function pulldownRefresh() {
var pageSize = parseInt($("input[name='page.pageSize']").val());
//其它参数
var type = parseInt($("input[name='params.type']").val());
//重置为第一页
$("input[name='page.currentPage']").val(1);
$.ajax({
type : "POST",
//这里的pageSize,可以只刷新一页的数据,也可以刷新已经加载出来的数据,需要简单计算一下
url : $("#moreForm").attr("action") + "?type=" + type
+ "&page.currentPage=1" + "&page.pageSize=" + pageSize,
data : $("#moreForm").serialize(),
async : false,
dataType : "text",
success : function(data) {
//将新的列表标签追加到对应列表下面
$("#pullrefresh .mui-scroll .article-list").html($.trim(data));
}
});
//结束下拉刷新
mui('#pullrefresh').pullRefresh().endPulldownToRefresh();
//重置上拉
mui('#pullrefresh').pullRefresh().refresh(true);
}
说明一下,我这里是重新刷新一页的数据,也可以刷新已经加载出来的数据,数据获取完成后结束刷新就行了。另外这个action返回的是子页面的整个HTML标签代码,所以就直接append到对应的ul下面就可以了,不用使用模板引擎拼接了。
<div id="pullrefresh" class="mui-scroll-wrapper">
<div class="mui-scroll">
<!--数据列表-->
<ul class="mui-table-view-chevron article-list">
<jsp:include page="/pages/article/articleListItem.jsp" flush="true" />
</ul>
</div>
加载更多业务处理方法:
// 上拉加载具体业务实现
function pullupRefresh() {
var currentPage = parseInt($("input[name='page.currentPage']").val());
var totalPage = parseInt($("input[name='page.totalPage']").val());
var pageSize = parseInt($("input[name='page.pageSize']").val());
//其它参数
var type = parseInt($("input[name='params.type']").val());
if (currentPage < totalPage) {
$("input[name='page.currentPage']").val(currentPage + 1);
$.ajax({
type : "POST",
url : $("#moreForm").attr("action") + "?type=" + type
+ "&page.currentPage=" + (currentPage + 1)
+ "&page.pageSize=" + pageSize,
data : $("#moreForm").serialize(),
async : false,
dataType : "text",
success : function(data) {
$("#pullrefresh .mui-scroll .article-list")
.append($.trim(data));
}
});
}
//判断新增一页后是否还可以刷新
mui('#pullrefresh').pullRefresh().endPullupToRefresh(
currentPage + 1 >= totalPage);
}
如果拉完已经是最后一页,上拉就会关闭,下面的提示文字会变成类似'没有更多数据'这样的,使用起来还是挺简单的。
把页面放在微信浏览器的时候,测试到一个现象,从列表页面进入详情然后再返回的时候,页面会自动刷新,这个时候需要重置上拉,不然就拉不动了,当然其它情况,比如有tab切换的时候也需要重置上拉刷新:
/**刷新事件,从微信详情页面返回列表后,重置刷新*/
window.addEventListener('refresh', function(e) {
var currentPage = parseInt($("input[name='page.currentPage']").val());
if (currentPage > 1) {
$("input[name='page.currentPage']").val(1);
setTimeout(function() {
//重置上拉
mui('#pullrefresh').pullRefresh().refresh(true);
}, 1000);
}
});
关键代码就是有注释那一句,这里设置了一个延迟,不然刷新的时候会触发两次上拉,这可能是mui的一个bug,加上这个延迟反复测试过就没这个现象了。
今天就介绍到这里,有什么问题欢迎留言或者关注技术公众号以及加技术群交流进行交流。