近期做了一個項目需要用到下拉刷新,上拉加載更多,無意間在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); } }