1. 首先献上官网地址和资源
官网:http://www.mescroll.com/
js,css百度云链接:https://pan.baidu.com/s/1_WV5BQ2N2TLhfpW_U9GHxw
密码:44cy
mescroll.js
mescroll.css
mescroll-option.js
mescroll-option.css
2.具体前端后端代码(html没有加入其他样式)
引入上面的js和css
<div id="mescroll" class="mescroll"> //id可以改,而"mescroll"的class不能删
<div id="dataList" class="data-list">
</div>
</div>
<script type="text/javascript">
$(function(){
//创建MeScroll对象
var mescroll = initMeScroll("mescroll", {
up: {
clearEmptyId:"dataList",//上面的id
isBoth: true, //上拉加载时,如果滑动到列表顶部是否可以同时触发下拉刷新;默认false,两者不可同时触发; 这里为了演示改为true,不必等列表加载完毕才可下拉;
isBounce: true, //此处禁止ios回弹,解析(务必认真阅读,特别是最后一点): http://www.mescroll.com/qa.html#q10
callback: getListData, //上拉加载的回调
toTop:{ //配置回到顶部按钮
src : "themes/option/mescroll-totop.png", //默认滚动到1000px显示,可配置offset修改
//offset : 1000
}
},
});
/*初始化菜单*/
var pdType=0;//全部商品0; 奶粉1; 图书2;这个我默认为0了,我的商品没有分类
/* $(".nav p").click(function(){
var i=$(this).attr("i");
if(pdType!=i) {
//更改列表条件
pdType=i;
$(".nav .active").removeClass("active");
$(this).addClass("active");
//重置列表数据
mescroll.resetUpScroll();
}
}) */
/*联网加载列表数据 page = {num:1, size:10}; num:当前页 从1开始, size:每页数据条数 */
function getListData(page){
//联网加载数据
getListDataFromNet(pdType, page.num, page.size, function(curPageData){
//联网成功的回调,隐藏下拉刷新和上拉加载的状态;
//mescroll会根据传的参数,自动判断列表如果无任何数据,则提示空;列表无下一页数据,则提示无更多数据;
console.log("pdType="+pdType+", page.num="+page.num+", page.size="+page.size+", curPageData.length="+curPageData.length);
//alert(curPageData.length);
//alert(page.num);
//alert(page.size);
//方法一(推荐): 后台接口有返回列表的总页数 totalPage
//mescroll.endByPage(curPageData.length, totalPage); //必传参数(当前页的数据个数, 总页数)
//方法二(推荐): 后台接口有返回列表的总数据量 totalSize
//mescroll.endBySize(curPageData.length, totalSize); //必传参数(当前页的数据个数, 总数据量)
//方法三(推荐): 您有其他方式知道是否有下一页 hasNext
//mescroll.endSuccess(curPageData.length, hasNext); //必传参数(当前页的数据个数, 是否有下一页true/false)
//方法四 (不推荐),会存在一个小问题:比如列表共有20条数据,每页加载10条,共2页.如果只根据当前页的数据个数判断,则需翻到第三页才会知道无更多数据,如果传了hasNext,则翻到第二页即可显示无更多数据.
//mescroll.endSuccess(curPageData.length);
mescroll.endSuccess(curPageData.length);
//设置列表数据
setListData(curPageData);
}, function(){
//联网失败的回调,隐藏上拉加载的状态
mescroll.endErr();
});
}
/*设置列表数据*/
function setListData(curPageData){
var listDom=document.getElementById("dataList");
for (var i = 0; i < curPageData.length; i++) {
var pd=curPageData[i];
var uuid = "${uuid}";
//html拼接
var str="<div class='hot_prod_list'>"+
"<div class='box pos_rel'>"+
"<a href='../ShopIndex/products/"+pd.uuid+"/"+uuid+"'><img src='"+pd.goodPhoto+"' height='150' width='150'></a>"+
"<h4><a href='../ShopIndex/products/"+pd.uuid+"/"+uuid+"'>"+pd.goodName+"</a></h4>"+
"<div class='price'><span class='red new'>¥<i>"+pd.goodPrice+"</i></span><span class='old'>¥<i>"+pd.remark+"</i></span></div>"+
"<a href='../ShopIndex/products/"+pd.uuid+"/"+uuid+"' class='btn_buy red pos_abs'>立即抢购</a>"+
"</div>"+
"</div>";
$("#dataList").append(str);
}
}
/*联网加载列表数据
在您的实际项目中,请参考官方写法: http://www.mescroll.com/api.html#tagUpCallback
请忽略getListDataFromNet的逻辑,这里仅仅是在本地模拟分页数据,本地演示用
实际项目以您服务器接口返回的数据为准,无需本地处理分页.
* */
function getListDataFromNet(pdType,pageNum,pageSize,successCallback,errorCallback) {
//延时0.5秒,模拟联网
setTimeout(function () {
$.ajax({
type: 'GET',
url:'../ShopIndex/indexPage/${uuid}',
//data : {"uuid" : uuid},
dataType: 'json',
success: function(data){
//alert(data);//通过ajax请求得到的数据
var listData=[];
//pdType 全部商品0;这个前面设置的,本来有0,1,2便于分类,我这边只有一个就注释了
if(pdType==0){
//全部商品 (模拟分页数据)
for (var i = (pageNum-1)*pageSize; i < pageNum*pageSize; i++) {
if(i==data.goodlist.length) break;
listData.push(data.goodlist[i]);
}
}
//回调
successCallback(listData);
},
error: errorCallback
});
},500)//设置加载时间
}
});
</script>
3.讲解
其实上面的很多在mescroll.js里面都有详细的注解
//下拉刷新的配置
MeScroll.extend(optDown, {
use: true, //是否启用下拉刷新; 默认true
auto: true, //是否在初始化完毕之后自动执行下拉刷新的回调; 默认true
autoShowLoading: false, //如果设置auto=true(在初始化完毕之后自动执行下拉刷新的回调),那么是否显示下拉刷新的进度; 默认false
isLock: false, //是否锁定下拉刷新,默认false;
isBoth: false, //下拉刷新时,如果滑动到列表底部是否可以同时触发上拉加载;默认false,两者不可同时触发;
offset: 80, //在列表顶部,下拉大于80px,松手即可触发下拉刷新的回调
outOffsetRate: 0.2, //在列表顶部,下拉的距离大于offset时,改变下拉区域高度比例;值小于1且越接近0,高度变化越小,表现为越往下越难拉
bottomOffset: 20, //当手指touchmove位置在距离body底部20px范围内的时候结束上拉刷新,避免Webview嵌套导致touchend事件不执行
minAngle: 45, //向下滑动最少偏移的角度,取值区间 [0,90];默认45度,即向下滑动的角度大于45度则触发下拉;而小于45度,将不触发下拉,避免与左右滑动的轮播等组件冲突;
hardwareClass: "mescroll-hardware", //硬件加速样式,解决部分手机闪屏或动画不流畅的问题
warpId: null, //可配置下拉刷新的布局添加到指定id的div;默认不配置,默认添加到mescrollId
warpClass: "mescroll-downwarp", //下拉刷新的布局容器样式,参见mescroll.css
resetClass: "mescroll-downwarp-reset", //下拉刷新高度重置的动画,参见mescroll.css
htmlContent: '<p class="downwarp-progress"></p><p class="downwarp-tip">下拉刷新 </p>', //布局内容
inited: function(mescroll, downwarp) {
//下拉刷新初始化完毕的回调
mescroll.downTipDom = downwarp.getElementsByClassName("downwarp-tip")[0];
mescroll.downProgressDom = downwarp.getElementsByClassName("downwarp-progress")[0];
},
inOffset: function(mescroll) {
//下拉的距离进入offset范围内那一刻的回调
if(mescroll.downTipDom) mescroll.downTipDom.innerHTML = "下拉刷新";
if(mescroll.downProgressDom) mescroll.downProgressDom.classList.remove("mescroll-rotate");
},
outOffset: function(mescroll) {
//下拉的距离大于offset那一刻的回调
if(mescroll.downTipDom) mescroll.downTipDom.innerHTML = "释放更新";
},
onMoving: function(mescroll, rate, downHight) {
//下拉过程中的回调,滑动过程一直在执行; rate下拉区域当前高度与指定距离的比值(inOffset: rate<1; outOffset: rate>=1); downHight当前下拉区域的高度
if(mescroll.downProgressDom) {
var progress = 360 * rate;
mescroll.downProgressDom.style.webkitTransform = "rotate(" + progress + "deg)";
mescroll.downProgressDom.style.transform = "rotate(" + progress + "deg)";
}
},
beforeLoading: function(mescroll, downwarp) {
//准备触发下拉刷新的回调
return false; //如果return true,将不触发showLoading和callback回调; 常用来完全自定义下拉刷新, 参考案例【淘宝 v6.8.0】
},
showLoading: function(mescroll) {
//显示下拉刷新进度的回调
if(mescroll.downTipDom) mescroll.downTipDom.innerHTML = "加载中 ...";
if(mescroll.downProgressDom) mescroll.downProgressDom.classList.add("mescroll-rotate");
},
callback: function(mescroll) {
//下拉刷新的回调;默认重置上拉加载列表为第一页
mescroll.resetUpScroll();
}
})
}
/*配置参数:上拉加载*/
MeScroll.prototype.extendUpScroll = function(optUp) {
//是否为PC端,如果是scrollbar端,默认自定义滚动条
var isPC = this.os.pc;
//上拉加载的配置
MeScroll.extend(optUp, {
use: true, //是否启用上拉加载; 默认true
auto: true, //是否在初始化完毕之后自动执行上拉加载的回调; 默认true
isLock: false, //是否锁定上拉加载,默认false;
isBoth: false, //上拉加载时,如果滑动到列表顶部是否可以同时触发下拉刷新;默认false,两者不可同时触发;
isBounce: true, //是否允许ios的bounce回弹;默认true,允许; 如果设置为false,则除了mescroll, mescroll-touch, mescroll-touch-x, mescroll-touch-y能够接收touchmove事件,其他部分均无法滑动,能够有效禁止bounce
callback: null, //上拉加载的回调;function(page,mescroll){ }
page: {
num: 0, //当前页码,默认0,回调之前会加1,即callback(page)会从1开始
size: 10, //每页数据的数量
time: null //加载第一页数据服务器返回的时间; 防止用户翻页时,后台新增了数据从而导致下一页数据重复;
},
noMoreSize: 5, //如果列表已无数据,可设置列表的总数量要大于等于5条才显示无更多数据;避免列表数据过少(比如只有一条数据),显示无更多数据会不好看
offset: 100, //列表滚动到距离底部小于100px,即可触发上拉加载的回调
toTop: {
//回到顶部按钮,需配置src才显示
warpId: null, //父布局的id; 默认添加在body中
src: null, //图片路径,默认null;
html: null, //html标签内容,默认null; 如果同时设置了src,则优先取src
offset: 1000, //列表滚动多少距离才显示回到顶部按钮,默认1000
warpClass: "mescroll-totop", //按钮样式,参见mescroll.css
showClass: "mescroll-fade-in", //显示样式,参见mescroll.css
hideClass: "mescroll-fade-out", //隐藏样式,参见mescroll.css
duration: 300, //回到顶部的动画时长,默认300ms
supportTap: false //如果您的运行环境支持tap,则可配置true;
},
loadFull: {
use: false, //列表数据过少,不足以滑动触发上拉加载,是否自动加载下一页,直到满屏或者无更多数据为止;默认false,因为可通过调高page.size避免这个情况
delay: 500 //延时执行的毫秒数; 延时是为了保证列表数据或占位的图片都已初始化完成,且下拉刷新上拉加载中区域动画已执行完毕;
},
empty: {
//列表第一页无任何数据时,显示的空提示布局; 需配置warpId或clearEmptyId才生效;
warpId: null, //父布局的id; 如果此项有值,将不使用clearEmptyId的值;
icon: null, //图标路径
tip: "暂无相关数据~", //提示
btntext: "", //按钮
btnClick: null, //点击按钮的回调
supportTap: false //如果您的运行环境支持tap,则可配置true;
},
clearId: null, //加载第一页时需清空数据的列表id; 如果此项有值,将不使用clearEmptyId的值;
clearEmptyId: null, //相当于同时设置了clearId和empty.warpId; 简化写法;
hardwareClass: "mescroll-hardware", //硬件加速样式,使上拉动画流畅
warpId: null, //可配置上拉加载的布局添加到指定id的div;默认不配置,默认添加到mescrollId
warpClass: "mescroll-upwarp", //上拉加载的布局容器样式
htmlLoading: '<p class="upwarp-progress mescroll-rotate"></p><p class="upwarp-tip">加载中..</p>', //上拉加载中的布局
htmlNodata: '<p class="upwarp-nodata">-- END --</p>', //无数据的布局
inited: function(mescroll, upwarp) {
//初始化完毕的回调,可缓存dom 比如 mescroll.upProgressDom = upwarp.getElementsByClassName("upwarp-progress")[0];
},
showLoading: function(mescroll, upwarp) {
//上拉加载中.. mescroll.upProgressDom.style.display = "block" 不通过此方式显示,因为ios快速滑动到底部,进度条会无法及时渲染
upwarp.innerHTML = mescroll.optUp.htmlLoading;
},
showNoMore: function(mescroll, upwarp) {
//无更多数据
upwarp.innerHTML = mescroll.optUp.htmlNodata;
},
onScroll: null, //列表滑动监听,默认null; 例如 onScroll: function(mescroll, y, isUp){ }; //y为列表当前滚动条的位置; isUp=true向上滑,isUp=false向下滑
scrollbar: {
use: isPC, //默认只在PC端自定义滚动条样式
barClass: "mescroll-bar"
}
})
我代码里的下拉刷新没有重新写,所以只有一个up(上拉加载),如果重新写,就是down,格式照着up就可以了,但是里面的参数就需要对着上面的js来写。
我写这个功能的时候是在微信公众号里面,一个商城,主要应用在商城首页商品的展示,我的订单的查询。这个框架是自带类似分页功能的的,上拉加载拉一次就加载后面的一页,一页10条数据,可在js里面修改,加载快慢也可以修改,这些都不是问题,问题主要还是这个MeScroll样式会与原来页面样式冲突,这就需要手动调试,我说的样式并不是排版,而是一些适配问题,因为是公众号一般是在手机上使用,我调试的时候是在谷歌浏览器上模拟的手机尺寸进行的,手机和电脑的区别是在你向下或者向上滑动时,电脑用的是鼠标滚轮,而手机是用的手指,用手指就意味着会按住屏幕,当你向上向下滑动时,会认为你在时时的上拉加载,或者下拉刷新,导致你认为正常的滑动变得非常缓慢甚至卡死。
其实这个前段框架在js部分就已经区别了手机端和电脑端,甚至还专门适配的ios的部分效果,所以归根到底就是我的前端样式出了问题,刚开始我一直以为js部分会有解决这个问题的参数,只需要设置true和false就可以了,但是我从头到尾看了一遍,发现没有,这时我就不开心了。到网上找了下这个问题的原因,发现几乎没有人讲到这个,但是有个类似的问题说可能是样式的问题,我就看了看,从前端样式入手,调了很多次,差点把页面调崩了,但是可喜的是最后还是调好了,原来
<div id="mescroll" class="mescroll"> //id可以改,而"mescroll"的class不能删
<div id="dataList" class="data-list">
</div>
</div>
这个里面<div id="mescroll" class="mescroll"></div>包含的范围应该是整个<body></body>里面的所有内容,当然了,还是要视情况而定,反正范围要大,而且class="mescroll"和 class="data-list"里的样式根据你原本的页面样式还要重写
/*列表*/
.mescroll{
position: fixed;//生成绝对定位的元素,相对于浏览器窗口进行定位
top: 44px;
bottom: 44px;
height: auto;
}
/*展示上拉加载的数据列表*/
.data-list div{
position: relative;//生成相对定位的元素,相对于其正常位置进行定位。
}
这个也要重写,body,当然了,这就要看原本的格式问题
html,body{
padding-top:0.92rem;
}
写到这里就要结束啦。
展示下效果图:
下拉刷新:
上拉加载:
当没有数据可加载后: