DEMO : 滾動加載示例
關於如何實現『加載更多』功能,網上有插件可用,例如比較著名的使用iscroll.js實現的上拉加載更多、下拉刷新功能。
但實際用起來卻是很麻煩。由於是第三方插件,要按照對方定義的方法使用,用起來總感覺很不順心。再加上iscroll.js本身並沒有集成加載更多的功能,需要進行自行擴展。想繼續使用iscroll.js實現加載更多功能的,上面給的鏈接可以看看。
h5項目里需要實現簡單的分頁功能,由於是移動端,考慮用『加載更多』會更好,而不是PC端的翻頁。
基於按鈕實現加載更多
最簡單的就是給一個加載更多的按鈕,如果還有數據,點擊下加載更多,繼續拉幾條數據;直到沒有更多數據了,隱藏加載更多按鈕。
DEMO : 基於按鈕實現加載更多
這里提前准備好數據。
演示數據格式:blog.json
{
"list": [
{
"title": "這是title",
"url": "http://www.cnblogs.com/52fhy/p/5271447.html",
"desc": "摘要"
},
{
"title": "這是title2",
"url": "http://www.cnblogs.com/52fhy/p/4823390.html",
"desc": "摘要"
}]
}
頁面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調用成功后才決定顯示與否*/
}
加載更多的js代碼:
$(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);
});
});
這里的代碼並不多。其中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!');
}
});
}
還是比較簡單的。
基於滾動事件實現加載更多
上面我們通過按鈕點擊實現加載更多,整體過程還是比較簡單的。這里,我提供另一種方法實現加載更多:基於於滾動(scroll
)事件。
DEMO : 基於滾動事件實現加載更多
直接貼代碼了:
$(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);
}
});
});
可以看出,代碼變化不大,主要看核心代碼里的判斷條件:當滾動到最底部以上100像素時, 加載新內容。
業務邏輯getData(pageStart, pageSize)
只需要把if ( (offset + size) >= sum)
里面的邏輯改成:
if ( (offset + size) >= sum){
isEnd = true;//沒有更多了
}
就行了。
當然,這里面還有要優化的地方,例如:
如何防止滾動過快,服務端沒來得及響應造成多次請求?
綜合實例
通過上面的例子,顯然第二種更好,不用去點擊。但是第二個方法有個問題:
如果設置頁面大小每次顯示2條或3條(size=2),總記錄是20,你會發現無法觸發向下滾動加載更多的邏輯。這時候有個加載更多的點擊按鈕就好了。
因此,我們可以把以上兩種方法合在一起:
默認使用滾動事件實現加載更多,當顯示數目太小不足以觸發向下滾動加載更多的邏輯時,使用加載更多點擊事件。
DEMO : 綜合實例
這里,我對加載更多這個行為進行簡單的抽象,寫了個簡單的插件:
loadmore.js
/*
* 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);
如何使用呢?很簡單:
$.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!');
}
});
}
基本上與最初寫的是一樣的。
示例代碼托管在Github: https://github.com/52fhy/loadmore
-- 全文完 --