近期做了一个项目需要用到下拉刷新,上拉加载更多,无意间在GitHub上面发现了这个插件,很小,只依赖于jQuery或Zepto就可运行。使用也很简单,下面贴上示例:
插件内容我就直接贴在博客最后面了,复制粘贴就能用了:
下面直接上示例:
示例一、加载底部
<script>
$(function(){
// 页数
var page = 0;
// 每页展示5个
var size = 5;
// dropload调用
$('.content').dropload({
scrollArea : window,
loadDownFn : function(me){
page++;
// 拼接HTML
var result = '';
$.ajax({
type: 'GET',
url: 'http://ons.me/tools/dropload/json.php?page='+page+'&size='+size,//配合后台接口
dataType: 'json',
success: function(data){
var arrLen = data.length;
if(arrLen > 0){
for(var i=0; i<arrLen; i++){
result += '<a class="item opacity" href="'+data[i].link+'">'
+'<img src="'+data[i].pic+'" alt="">'
+'<h3>'+data[i].title+'</h3>'
+'<span class="date">'+data[i].date+'</span>'
+'</a>';
}
// 如果没有数据
}else{
// 锁定
me.lock();
// 无数据
me.noData();
}
// 为了测试,延迟1秒加载
setTimeout(function(){
// 插入数据到页面,放到最后面
$('.lists').append(result);
// 每次数据插入,必须重置
me.resetload();
},1000);
},
error: function(xhr, type){
alert('Ajax error!');
// 即使加载出错,也得重置
me.resetload();
}
});
}
});
});
</script>
示例二、加载顶部、底部
<script>
$(function(){
// 页数
var page = 0;
// 每页展示10个
var size = 10;
// dropload
$('.content').dropload({
scrollArea : window,
domUp : {
domClass : 'dropload-up',
domRefresh : '<div class="dropload-refresh">↓下拉刷新-自定义内容</div>',
domUpdate : '<div class="dropload-update">↑释放更新-自定义内容</div>',
domLoad : '<div class="dropload-load"><span class="loading"></span>加载中-自定义内容...</div>'
},
domDown : {
domClass : 'dropload-down',
domRefresh : '<div class="dropload-refresh">↑上拉加载更多-自定义内容</div>',
domLoad : '<div class="dropload-load"><span class="loading"></span>加载中-自定义内容...</div>',
domNoData : '<div class="dropload-noData">暂无数据-自定义内容</div>'
},
loadUpFn : function(me){
$.ajax({
type: 'GET',
url: 'json/update.json',
dataType: 'json',
success: function(data){
var result = '';
for(var i = 0; i < data.lists.length; i++){
result += '<a class="item opacity" href="'+data.lists[i].link+'">'
+'<img src="'+data.lists[i].pic+'" alt="">'
+'<h3>'+data.lists[i].title+'</h3>'
+'<span class="date">'+data.lists[i].date+'</span>'
+'</a>';
}
// 为了测试,延迟1秒加载
setTimeout(function(){
$('.lists').html(result);
// 每次数据加载完,必须重置
me.resetload();
// 重置页数,重新获取loadDownFn的数据
page = 0;
// 解锁loadDownFn里锁定的情况
me.unlock();
me.noData(false);
},1000);
},
error: function(xhr, type){
alert('Ajax error!');
// 即使加载出错,也得重置
me.resetload();
}
});
},
loadDownFn : function(me){
page++;
// 拼接HTML
var result = '';
$.ajax({
type: 'GET',
url: 'http://ons.me/tools/dropload/json.php?page='+page+'&size='+size,
dataType: 'json',
success: function(data){
var arrLen = data.length;
if(arrLen > 0){
for(var i=0; i<arrLen; i++){
result += '<a class="item opacity" href="'+data[i].link+'">'
+'<img src="'+data[i].pic+'" alt="">'
+'<h3>'+data[i].title+'</h3>'
+'<span class="date">'+data[i].date+'</span>'
+'</a>';
}
// 如果没有数据
}else{
// 锁定
me.lock();
// 无数据
me.noData();
}
// 为了测试,延迟1秒加载
setTimeout(function(){
// 插入数据到页面,放到最后面
$('.lists').append(result);
// 每次数据插入,必须重置
me.resetload();
},1000);
},
error: function(xhr, type){
alert('Ajax error!');
// 即使加载出错,也得重置
me.resetload();
}
});
},
threshold : 50
});
});
</script>
示例三、多次加载
$(function(){
//利用此写法,可以限制多次加载的个数。
var timer;
$('.header .ipt').on('input',function(){
var _length = $(this).val();
// 如果输入值不是数字或者是空,就跳出
if(isNaN(_length) || _length === ''){
return false;
}
clearTimeout(timer);
timer = setTimeout(function(){//也可不用定时器
// 清空内容
$('.lists').html('');
$('.dropload-down').remove();
var counter = 0;
// 每页展示4个
var num = 4;
var pageStart = 0,pageEnd = 0;
// dropload
$('.content').dropload({
scrollArea : window,
loadDownFn : function(me){
$.ajax({
type: 'GET',
url: 'json/more.json',
dataType: 'json',
success: function(data){
var result = '';
counter++;
pageEnd = num * counter;
pageStart = pageEnd - num;
for(var i = pageStart; i < pageEnd; i++){
result += '<a class="item opacity" href="'+data.lists[i].link+'">'
+'<img src="'+data.lists[i].pic+'" alt="">'
+'<h3>'+data.lists[i].title+'</h3>'
+'<span class="date">'+data.lists[i].date+'</span>'
+'</a>';
if((i + 1) >= _length || (i + 1) >= data.lists.length){
// 锁定
me.lock();
// 无数据
me.noData();
break;
}
}
// 为了测试,延迟1秒加载
setTimeout(function(){
$('.lists').append(result);
// 每次数据加载完,必须重置
me.resetload();
},1000);
},
error: function(xhr, type){
alert('Ajax error!');
// 即使加载出错,也得重置
me.resetload();
}
});
}
});
},500);
});
示例四、固定布局,加载顶部、底部
$(function(){
// 按钮操作
$('.header .btn').on('click',function(){
var $this = $(this);
if(!!$this.hasClass('lock')){
$this.attr('class','btn unlock');
$this.text('解锁');
// 锁定
dropload.lock();
$('.dropload-down').hide();
}else{
$this.attr('class','btn lock');
$this.text('锁定');
// 解锁
dropload.unlock();
$('.dropload-down').show();
}
});
// dropload
var dropload = $('.inner').dropload({
domUp : {
domClass : 'dropload-up',
domRefresh : '<div class="dropload-refresh">↓下拉刷新</div>',
domUpdate : '<div class="dropload-update">↑释放更新</div>',
domLoad : '<div class="dropload-load"><span class="loading"></span>加载中...</div>'
},
domDown : {
domClass : 'dropload-down',
domRefresh : '<div class="dropload-refresh">↑上拉加载更多</div>',
domLoad : '<div class="dropload-load"><span class="loading"></span>加载中...</div>',
domNoData : '<div class="dropload-noData">暂无数据</div>'
},
loadUpFn : function(me){
$.ajax({
type: 'GET',
url: 'json/update.json',
dataType: 'json',
success: function(data){
var result = '';
for(var i = 0; i < data.lists.length; i++){
result += '<a class="item opacity" href="'+data.lists[i].link+'">'
+'<img src="'+data.lists[i].pic+'" alt="">'
+'<h3>'+data.lists[i].title+'</h3>'
+'<span class="date">'+data.lists[i].date+'</span>'
+'</a>';
}
// 为了测试,延迟1秒加载
setTimeout(function(){
$('.lists').html(result);
// 每次数据加载完,必须重置
dropload.resetload();
},1000);
},
error: function(xhr, type){
alert('Ajax error!');
// 即使加载出错,也得重置
dropload.resetload();
}
});
},
loadDownFn : function(me){
$.ajax({
type: 'GET',
url: 'json/more.json',
dataType: 'json',
success: function(data){
var result = '';
for(var i = 0; i < data.lists.length; i++){
result += '<a class="item opacity" href="'+data.lists[i].link+'">'
+'<img src="'+data.lists[i].pic+'" alt="">'
+'<h3>'+data.lists[i].title+'</h3>'
+'<span class="date">'+data.lists[i].date+'</span>'
+'</a>';
}
// 为了测试,延迟1秒加载
setTimeout(function(){
$('.lists').append(result);
// 每次数据加载完,必须重置
dropload.resetload();
},1000);
},
error: function(xhr, type){
alert('Ajax error!');
// 即使加载出错,也得重置
dropload.resetload();
}
});
}
});
});
示例五、tab加载多个数据
$(function(){
var itemIndex = 0;
var tab1LoadEnd = false;
var tab2LoadEnd = false;
// tab
$('.tab .item').on('click',function(){
var $this = $(this);
itemIndex = $this.index();
$this.addClass('cur').siblings('.item').removeClass('cur');
$('.lists').eq(itemIndex).show().siblings('.lists').hide();
// 如果选中菜单一
if(itemIndex == '0'){
// 如果数据没有加载完
if(!tab1LoadEnd){
// 解锁
dropload.unlock();
dropload.noData(false);
}else{
// 锁定
dropload.lock('down');
dropload.noData();
}
// 如果选中菜单二
}else if(itemIndex == '1'){
if(!tab2LoadEnd){
// 解锁
dropload.unlock();
dropload.noData(false);
}else{
// 锁定
dropload.lock('down');
dropload.noData();
}
}
// 重置
dropload.resetload();
});
var counter = 0;
// 每页展示4个
var num = 4;
var pageStart = 0,pageEnd = 0;
// dropload
var dropload = $('.content').dropload({
scrollArea : window,
loadDownFn : function(me){
// 加载菜单一的数据
if(itemIndex == '0'){
$.ajax({
type: 'GET',
url: 'json/more.json',
dataType: 'json',
success: function(data){
var result = '';
counter++;
pageEnd = num * counter;
pageStart = pageEnd - num;
if(pageStart <= data.lists.length){
for(var i = pageStart; i < pageEnd; i++){
result += '<a class="item opacity" href="'+data.lists[i].link+'">'
+'<img src="'+data.lists[i].pic+'" alt="">'
+'<h3>'+data.lists[i].title+'</h3>'
+'<span class="date">'+data.lists[i].date+'</span>'
+'</a>';
if((i + 1) >= data.lists.length){
// 数据加载完
tab1LoadEnd = true;
// 锁定
me.lock();
// 无数据
me.noData();
break;
}
}
// 为了测试,延迟1秒加载
setTimeout(function(){
$('.lists').eq(0).append(result);
// 每次数据加载完,必须重置
me.resetload();
},1000);
}
},
error: function(xhr, type){
alert('Ajax error!');
// 即使加载出错,也得重置
me.resetload();
}
});
// 加载菜单二的数据
}else if(itemIndex == '1'){
$.ajax({
type: 'GET',
url: 'json/update.json',
dataType: 'json',
success: function(data){
var result = '';
for(var i = 0; i < data.lists.length; i++){
result += '<a class="item opacity" href="'+data.lists[i].link+'">'
+'<img src="'+data.lists[i].pic+'" alt="">'
+'<h3>'+data.lists[i].title+'</h3>'
+'<span class="date">'+data.lists[i].date+'</span>'
+'</a>';
}
// 为了测试,延迟1秒加载
setTimeout(function(){
$('.lists').eq(1).append(result);
// 每次数据加载完,必须重置
me.resetload();
},1000);
},
error: function(xhr, type){
alert('Ajax error!');
// 即使加载出错,也得重置
me.resetload();
}
});
}
}
});
});
插件内容:
js部分:
/**
* dropload
* 西门(http://ons.me/526.html)
* 0.9.1(161205)
*/
;(function($){
'use strict';
var win = window;
var doc = document;
var $win = $(win);
var $doc = $(doc);
$.fn.dropload = function(options){
return new MyDropLoad(this, options);
};
var MyDropLoad = function(element, options){
var me = this;
me.$element = element;
// 上方是否插入DOM
me.upInsertDOM = false;
// loading状态
me.loading = false;
// 是否锁定
me.isLockUp = false;
me.isLockDown = false;
// 是否有数据
me.isData = true;
me._scrollTop = 0;
me._threshold = 0;
me.init(options);
};
// 初始化
MyDropLoad.prototype.init = function(options){
var me = this;
me.opts = $.extend(true, {}, {
scrollArea : me.$element, // 滑动区域
domUp : { // 上方DOM
domClass : 'dropload-up',
domRefresh : '<div class="dropload-refresh">↓下拉刷新</div>',
domUpdate : '<div class="dropload-update">↑释放更新</div>',
domLoad : '<div class="dropload-load"><span class="loading"></span>加载中...</div>'
},
domDown : { // 下方DOM
domClass : 'dropload-down',
domRefresh : '<div class="dropload-refresh">↑上拉加载更多</div>',
domLoad : '<div class="dropload-load"><span class="loading"></span>加载中...</div>',
domNoData : '<div class="dropload-noData">暂无数据</div>'
},
autoLoad : true, // 自动加载
distance : 50, // 拉动距离
threshold : '', // 提前加载距离
loadUpFn : '', // 上方function
loadDownFn : '' // 下方function
}, options);
// 如果加载下方,事先在下方插入DOM
if(me.opts.loadDownFn != ''){
me.$element.append('<div class="'+me.opts.domDown.domClass+'">'+me.opts.domDown.domRefresh+'</div>');
me.$domDown = $('.'+me.opts.domDown.domClass);
}
// 计算提前加载距离
if(!!me.$domDown && me.opts.threshold === ''){
// 默认滑到加载区2/3处时加载
me._threshold = Math.floor(me.$domDown.height()*1/3);
}else{
me._threshold = me.opts.threshold;
}
// 判断滚动区域
if(me.opts.scrollArea == win){
me.$scrollArea = $win;
// 获取文档高度
me._scrollContentHeight = $doc.height();
// 获取win显示区高度 —— 这里有坑
me._scrollWindowHeight = doc.documentElement.clientHeight;
}else{
me.$scrollArea = me.opts.scrollArea;
me._scrollContentHeight = me.$element[0].scrollHeight;
me._scrollWindowHeight = me.$element.height();
}
fnAutoLoad(me);
// 窗口调整
$win.on('resize',function(){
clearTimeout(me.timer);
me.timer = setTimeout(function(){
if(me.opts.scrollArea == win){
// 重新获取win显示区高度
me._scrollWindowHeight = win.innerHeight;
}else{
me._scrollWindowHeight = me.$element.height();
}
fnAutoLoad(me);
},150);
});
// 绑定触摸
me.$element.on('touchstart',function(e){
if(!me.loading){
fnTouches(e);
fnTouchstart(e, me);
}
});
me.$element.on('touchmove',function(e){
if(!me.loading){
fnTouches(e, me);
fnTouchmove(e, me);
}
});
me.$element.on('touchend',function(){
if(!me.loading){
fnTouchend(me);
}
});
// 加载下方
me.$scrollArea.on('scroll',function(){
me._scrollTop = me.$scrollArea.scrollTop();
// 滚动页面触发加载数据
if(me.opts.loadDownFn != '' && !me.loading && !me.isLockDown && (me._scrollContentHeight - me._threshold) <= (me._scrollWindowHeight + me._scrollTop)){
loadDown(me);
}
});
};
// touches
function fnTouches(e){
if(!e.touches){
e.touches = e.originalEvent.touches;
}
}
// touchstart
function fnTouchstart(e, me){
me._startY = e.touches[0].pageY;
// 记住触摸时的scrolltop值
me.touchScrollTop = me.$scrollArea.scrollTop();
}
// touchmove
function fnTouchmove(e, me){
me._curY = e.touches[0].pageY;
me._moveY = me._curY - me._startY;
if(me._moveY > 0){
me.direction = 'down';
}else if(me._moveY < 0){
me.direction = 'up';
}
var _absMoveY = Math.abs(me._moveY);
// 加载上方
if(me.opts.loadUpFn != '' && me.touchScrollTop <= 0 && me.direction == 'down' && !me.isLockUp){
e.preventDefault();
me.$domUp = $('.'+me.opts.domUp.domClass);
// 如果加载区没有DOM
if(!me.upInsertDOM){
me.$element.prepend('<div class="'+me.opts.domUp.domClass+'"></div>');
me.upInsertDOM = true;
}
fnTransition(me.$domUp,0);
// 下拉
if(_absMoveY <= me.opts.distance){
me._offsetY = _absMoveY;
// todo:move时会不断清空、增加dom,有可能影响性能,下同
me.$domUp.html(me.opts.domUp.domRefresh);
// 指定距离 < 下拉距离 < 指定距离*2
}else if(_absMoveY > me.opts.distance && _absMoveY <= me.opts.distance*2){
me._offsetY = me.opts.distance+(_absMoveY-me.opts.distance)*0.5;
me.$domUp.html(me.opts.domUp.domUpdate);
// 下拉距离 > 指定距离*2
}else{
me._offsetY = me.opts.distance+me.opts.distance*0.5+(_absMoveY-me.opts.distance*2)*0.2;
}
me.$domUp.css({'height': me._offsetY});
}
}
// touchend
function fnTouchend(me){
var _absMoveY = Math.abs(me._moveY);
if(me.opts.loadUpFn != '' && me.touchScrollTop <= 0 && me.direction == 'down' && !me.isLockUp){
fnTransition(me.$domUp,300);
if(_absMoveY > me.opts.distance){
me.$domUp.css({'height':me.$domUp.children().height()});
me.$domUp.html(me.opts.domUp.domLoad);
me.loading = true;
me.opts.loadUpFn(me);
}else{
me.$domUp.css({'height':'0'}).on('webkitTransitionEnd mozTransitionEnd transitionend',function(){
me.upInsertDOM = false;
$(this).remove();
});
}
me._moveY = 0;
}
}
// 如果文档高度不大于窗口高度,数据较少,自动加载下方数据
function fnAutoLoad(me){
if(me.opts.loadDownFn != '' && me.opts.autoLoad){
if((me._scrollContentHeight - me._threshold) <= me._scrollWindowHeight){
loadDown(me);
}
}
}
// 重新获取文档高度
function fnRecoverContentHeight(me){
if(me.opts.scrollArea == win){
me._scrollContentHeight = $doc.height();
}else{
me._scrollContentHeight = me.$element[0].scrollHeight;
}
}
// 加载下方
function loadDown(me){
me.direction = 'up';
me.$domDown.html(me.opts.domDown.domLoad);
me.loading = true;
me.opts.loadDownFn(me);
}
// 锁定
MyDropLoad.prototype.lock = function(direction){
var me = this;
// 如果不指定方向
if(direction === undefined){
// 如果操作方向向上
if(me.direction == 'up'){
me.isLockDown = true;
// 如果操作方向向下
}else if(me.direction == 'down'){
me.isLockUp = true;
}else{
me.isLockUp = true;
me.isLockDown = true;
}
// 如果指定锁上方
}else if(direction == 'up'){
me.isLockUp = true;
// 如果指定锁下方
}else if(direction == 'down'){
me.isLockDown = true;
// 为了解决DEMO5中tab效果bug,因为滑动到下面,再滑上去点tab,direction=down,所以有bug
me.direction = 'up';
}
};
// 解锁
MyDropLoad.prototype.unlock = function(){
var me = this;
// 简单粗暴解锁
me.isLockUp = false;
me.isLockDown = false;
// 为了解决DEMO5中tab效果bug,因为滑动到下面,再滑上去点tab,direction=down,所以有bug
me.direction = 'up';
};
// 无数据
MyDropLoad.prototype.noData = function(flag){
var me = this;
if(flag === undefined || flag == true){
me.isData = false;
}else if(flag == false){
me.isData = true;
}
};
// 重置
MyDropLoad.prototype.resetload = function(){
var me = this;
if(me.direction == 'down' && me.upInsertDOM){
me.$domUp.css({'height':'0'}).on('webkitTransitionEnd mozTransitionEnd transitionend',function(){
me.loading = false;
me.upInsertDOM = false;
$(this).remove();
fnRecoverContentHeight(me);
});
}else if(me.direction == 'up'){
me.loading = false;
// 如果有数据
if(me.isData){
// 加载区修改样式
me.$domDown.html(me.opts.domDown.domRefresh);
fnRecoverContentHeight(me);
fnAutoLoad(me);
}else{
// 如果没数据
me.$domDown.html(me.opts.domDown.domNoData);
}
}
};
// css过渡
function fnTransition(dom,num){
dom.css({
'-webkit-transition':'all '+num+'ms',
'transition':'all '+num+'ms'
});
}
})(window.Zepto || window.jQuery);
css部分:
.dropload-up,.dropload-down{
position: relative;
height: 0;
overflow: hidden;
font-size: 12px;
/* 开启硬件加速 */
-webkit-transform:translateZ(0);
transform:translateZ(0);
}
.dropload-down{
height: 50px;
}
.dropload-refresh,.dropload-update,.dropload-load,.dropload-noData{
height: 50px;
line-height: 50px;
text-align: center;
}
.dropload-load .loading{
display: inline-block;
height: 15px;
width: 15px;
border-radius: 100%;
margin: 6px;
border: 2px solid #666;
border-bottom-color: transparent;
vertical-align: middle;
-webkit-animation: rotate 0.75s linear infinite;
animation: rotate 0.75s linear infinite;
}
@-webkit-keyframes rotate {
0% {
-webkit-transform: rotate(0deg);
}
50% {
-webkit-transform: rotate(180deg);
}
100% {
-webkit-transform: rotate(360deg);
}
}
@keyframes rotate {
0% {
transform: rotate(0deg);
}
50% {
transform: rotate(180deg);
}
100% {
transform: rotate(360deg);
}
}