專案的一個前端頁面展示已購買商品時,要求能下拉加載更多。關於如何實現『載入更多』功能,網路上有插件可用,例如比較著名的使用iscroll.js實現的上拉加載更多、下拉刷新功能。
但實際用起來卻是很麻煩。由於是第三方插件,要按照對方定義的方法使用,用起來總覺得很不順心。再加上iscroll.js本身並沒有整合載入更多的功能,需要進行自行擴充。想繼續使用iscroll.js實作載入更多功能的,上面給的連結可以看看。
h5專案裡需要實現簡單的分頁功能,由於是行動端,考慮用『載入更多』會更好,而不是PC端的翻頁。
基於按鈕實現加載更多
最簡單的就是給一個加載更多的按鈕,如果還有數據,點擊下加載更多,繼續拉幾條數據;直到沒有更多數據了,隱藏加載更多按鈕。
效果如下:
頁html:
<div class="content"> <div class="weui_panel weui_panel_access"> <div class="weui_panel_hd">文章列表</div> <div class="weui_panel_bd js-blog-list"> </div> </div> <!--加载更多按钮--> <div class="js-load-more">加载更多</div> </div> <script src="js/zepto.min.js"></script>
載入更多按鈕樣式:loadmore.css:
@charset "utf-8"; .js-load-more{ padding:0 15px; width:120px; height:30px; background-color:#D31733; color:#fff; line-height:30px; text-align:center; border-radius:5px; margin:20px auto; border:0 none; font-size:16px; display:none;/*默认不显示,ajax调用成功后才决定显示与否*/ }
$(function(){ /*初始化*/ var counter = 0; /*计数器*/ var pageStart = 0; /*offset*/ var pageSize = 4; /*size*/ /*首次加载*/ getData(pageStart, pageSize); /*监听加载更多*/ $(document).on('click', '.js-load-more', function(){ counter ++; pageStart = counter * pageSize; getData(pageStart, pageSize); }); });
function getData(offset,size){ $.ajax({ type: 'GET', url: 'json/blog.json', dataType: 'json', success: function(reponse){ var data = reponse.list; var sum = reponse.list.length; var result = ''; /****业务逻辑块:实现拼接html内容并append到页面*********/ //console.log(offset , size, sum); /*如果剩下的记录数不够分页,就让分页数取剩下的记录数 * 例如分页数是5,只剩2条,则只取2条 * * 实际MySQL查询时不写这个不会有问题 */ if(sum - offset < size ){ size = sum - offset; } /*使用for循环模拟SQL里的limit(offset,size)*/ for(var i=offset; i< (offset+size); i++){ result +='<div class="weui_media_box weui_media_text">'+ '<a href="'+ data[i].url +'" target="_blank"><h4 class="weui_media_title">'+ data[i].title +'</h4></a>'+ '<p class="weui_media_desc">'+ data[i].desc +'</p>'+ '</div>'; } $('.js-blog-list').append(result); /*******************************************/ /*隐藏more按钮*/ if ( (offset + size) >= sum){ $(".js-load-more").hide(); }else{ $(".js-load-more").show(); } }, error: function(xhr, type){ alert('Ajax error!'); } }); }
其中getData(pageStart, pageSize)是業務邏輯程式碼,負責從服務端拉去資料。這裡給個例子:
$(function(){ /*初始化*/ var counter = 0; /*计数器*/ var pageStart = 0; /*offset*/ var pageSize = 7; /*size*/ var isEnd = false;/*结束标志*/ /*首次加载*/ getData(pageStart, pageSize); /*监听加载更多*/ $(window).scroll(function(){ if(isEnd == true){ return; } // 当滚动到最底部以上100像素时, 加载新内容 // 核心代码 if ($(document).height() - $(this).scrollTop() - $(this).height()<100){ counter ++; pageStart = counter * pageSize; getData(pageStart, pageSize); } }); });
還是比較簡單的。
基於滾動事件實現加載更多
上面我們透過按鈕點擊實現加載更多,整體過程還是比較簡單的。這裡,我提供另一種方法實作載入更多:基於於滾動(scroll)事件。
直接貼程式碼了:
if ( (offset + size) >= sum){ isEnd = true;//没有更多了 }
可以看出,程式碼變化不大,主要看核心程式碼裡的判斷條件:當捲動到最底部以上100像素時, 載入新內容。
業務邏輯getData(pageStart, pageSize)只需要把if ( (offset + size) >= sum)裡面的邏輯改成:
/* * loadmore.js * 加载更多 * * @time 2016-4-18 17:40:25 * @author 飞鸿影~ * @email jiancaigege@163.com * 可以传的参数默认有:size,scroll 可以自定义 * */ ;(function(w,$){ var loadmore = { /*单页加载更多 通用方法 * * @param callback 回调方法 * @param config 自定义参数 * */ get : function(callback, config){ var config = config ? config : {}; /*防止未传参数报错*/ var counter = 0; /*计数器*/ var pageStart = 0; var pageSize = config.size ? config.size : 10; /*默认通过点击加载更多*/ $(document).on('click', '.js-load-more', function(){ counter ++; pageStart = counter * pageSize; callback && callback(config, pageStart, pageSize); }); /*通过自动监听滚动事件加载更多,可选支持*/ config.isEnd = false; /*结束标志*/ config.isAjax = false; /*防止滚动过快,服务端没来得及响应造成多次请求*/ $(window).scroll(function(){ /*是否开启滚动加载*/ if(!config.scroll){ return; } /*滚动加载时如果已经没有更多的数据了、正在发生请求时,不能继续进行*/ if(config.isEnd == true || config.isAjax == true){ return; } /*当滚动到最底部以上100像素时, 加载新内容*/ if ($(document).height() - $(this).scrollTop() - $(this).height()<100){ counter ++; pageStart = counter * pageSize; callback && callback(config, pageStart, pageSize); } }); /*第一次自动加载*/ callback && callback(config, pageStart, pageSize); }, } $.loadmore = loadmore; })(window, window.jQuery || window.Zepto);
就行了。
當然,這裡面還有要優化的地方,例如:如何防止滾動過快,服務端來不及回應造成多次請求?
綜合實例
透過上面的例子,顯然第二種更好,不用去點擊。但第二個方法有個問題:
如果設定頁面大小每次顯示2條或3條(size=2),總記錄是20,你會發現無法觸發向下滾動載入更多的邏輯。這時候有個加載更多的點擊按鈕就好了。
因此,我們可以把以上兩種方法合在一起:
默認使用滾動事件實現加載更多,當顯示數目太小不足以觸發向下滾動加載更多的邏輯時,使用加載更多點擊事件。
這裡,我對加載更多這個行為進行簡單的抽象,寫了個簡單的插件:
loadmore.js
$.loadmore.get(getData, { scroll: true, //默认是false,是否支持滚动加载 size:7, //默认是10 flag: 1, //自定义参数,可选,示例里没有用到 });
如何使用呢?很簡單:
function getData(config, offset,size){ config.isAjax = true; $.ajax({ type: 'GET', url: 'json/blog.json', dataType: 'json', success: function(reponse){ config.isAjax = false; var data = reponse.list; var sum = reponse.list.length; var result = ''; /************业务逻辑块:实现拼接html内容并append到页面*****************/ //console.log(offset , size, sum); /*如果剩下的记录数不够分页,就让分页数取剩下的记录数 * 例如分页数是5,只剩2条,则只取2条 * * 实际MySQL查询时不写这个 */ if(sum - offset < size ){ size = sum - offset; } /*使用for循环模拟SQL里的limit(offset,size)*/ for(var i=offset; i< (offset+size); i++){ result +='<div class="weui_media_box weui_media_text">'+ '<a href="'+ data[i].url +'" target="_blank"><h4 class="weui_media_title">'+ data[i].title +'</h4></a>'+ '<p class="weui_media_desc">'+ data[i].desc +'</p>'+ '</div>'; } $('.js-blog-list').append(result); /*******************************************/ /*隐藏more*/ if ( (offset + size) >= sum){ $(".js-load-more").hide(); config.isEnd = true; /*停止滚动加载请求*/ //提示没有了 }else{ $(".js-load-more").show(); } }, error: function(xhr, type){ alert('Ajax error!'); } }); }
第一個參數是回呼函數,也就是我們的業務邏輯。我把最後修改過的商業邏輯方法貼出來:
rrreee