最近在做卖东西的网站时遇到一个需求,浏览商品列表的翻页功能需要做成瀑布流加载模式,滚动条靠近底部时自动开始加载下一页。 一开始我想的办法是在滚动条位置改变的事件上增加一个回调方法,一旦接近底部就触发一次网络请求。这么做在pc上能满足需求,然而在移动端设备上调试的时候却发生了意外情况。。 移动端设备浏览器通常带手势操作,上滑隐藏导航条,下滑显示导航条。如果初始内容的高度不够,那么这个设定总是会导致滚动条事件不触发。 假设初始内容高度600px,设备高度630px,导航条高度40px,可以计算出窗口高度590px,导航条距离底部10px。在用户进行手势操作后,这些事件将被依次触发:导航条高度变化,窗口高度变化,滚动条位置改变。所以此时窗口高度变为630px,因为内容高度600px<窗口高度630px,所以在滚动条位置改变之前滚动条已经不存在了,所以滚动条事件自然不会被触发。 既然事件无法利用,那么用计时器监听滚动条位置变化是解决问题的最快办法了。最终代码如下:
<meta charset='utf-8' />
<script src='https://blog.xdelve.com/js-lib/plus/jquery.js'></script>
<style>
div{
position: absolute;
left:0;
top:0;
height:300px;
width:200px;
overflow-x:hidden;
overflow-y:scroll;
line-height: 3;
padding:10px;
}
</style>
<div id='c'></div>
<script>
// 滚动条到底部时自动加载下一页
// 设计要求:
// 1. 一个实例中最多只可能存在一个网络io等待
// 2. 如果本次请求失败,则立即重试
// 3. 如果本次请求超时,应该忽略本次返回结果
var pageloader=function(selector,params,handler){
var c=$(selector),page=null,lock=false;
params.page=params.page||1;
params.distance=params.distance||10;
params.timeout=params.timeout||3000;
if(!params.handler)throw alert('业务接口必填');
var r=setInterval(function(){
if(!lock && page!==null){
lock=true;
params.handler(page,function(p,data){
if(p!==page)return;
handler(page,data);
params.page++;
page=null;
lock=false;
},function(p){
lock=false;
console.log(p+'失败');
});
setTimeout(function(){
lock=false;
},params.timeout);
}
if(c.scrollTop()+c.outerHeight()+params.distance<c[0].scrollHeight)
return;
page=params.page;
},16);
// 销毁计时器
return {
destory:function(){
clearInterval(r);
}
};
};
var a=pageloader('div#c',{
// getlist模拟一个封装了网络请求业务接口,接收参数为:页码,成功时回调,失败时回调(失败回调可省)
handler:function getlist(page,success,fail){
// 模拟网络延时
setTimeout(function(){
// 以一定概率模拟成功和失败
if(Math.random()<.8)
success(page,'# '+page+', '+Math.random());
// 模拟传入成功收到的数据
else fail && fail(page); // 模拟失败
},500*(1+Math.random()*1|0));
}
},function(page,data){
// 页码和此页上的数据
c.innerHTML+='<span>page: '+page+' => '+data+'</span><br/>';
});
// 如果需要销毁这个实例,使用此代码
// a.destory();
</script>
相关文档
暂无
随便看看
畅言模块加载中