學校軟件工程讓寫課程設計(其實就是自選語言做個項目),感覺都是重復的東西就沒有很認真的去寫內容,更加注意寫一些之前沒有用過的東西。
因為一直都使用TP框架來寫PHP,TP又自帶分頁類,想到這里就想試試寫一個異步分頁,於是昨天用了4個小時思考帶調試寫來出來...
思路:
異步分頁和同步分頁最直觀的一點就是切換數據頁不用刷新頁面,然后用Jquery動態的來創建一些html元素並給與相應的顯示規則,結合后台請求來切換表格數據。切換表格數據不屬於分頁內容,因此這里只探討分頁空間本身。
實現:
接下來大致說一下我寫的這個分頁類
1 function Page(count,listRow,showPageCount,obj,getData){ 2 var o = {};//分頁對象 3 o.nowPage = 1;//當前為第幾頁 4 o.listRow = listRow;//一頁顯示多少條數據 5 o.getData = getData;//取數據的回調函數 6 o.obj = obj;//制定在那個元素后面顯示(Jquery對象) 7 o.count = count;//數據總數 8 //總頁數 9 o.totalPage = o.count% o.listRow == 0? parseInt(o.count/ o.listRow) : parseInt(o.count/ o.listRow+1); 10 //顯示多少個分頁按鈕 11 o.showPageCount = o.showPageCount < o.totalPage? o.showPageCount : o.totalPage; 12 o.first = 1;//第一個顯示的分頁按鈕是多少 13 //最后一個顯示的分頁按鈕是多少 14 o.last = o.totalPage > showPageCount?showPageCount: o.totalPage;
使用JS工廠創建對象,先說說參數列表:
參數 | 描述 |
count | 數據總數 |
listRow | 每頁顯示的數據數量 |
showPageCount | 顯示多少個分頁按鈕 |
obj | 在哪個對象后創建分頁控件 |
getData | 點擊按鈕事件后的回調函數,用於得到數據並修改界面UI |
對象屬性:
屬性 | 描述 |
nowPage | 當前是第幾頁 |
listRow | 一頁能顯示多少條數據 |
getData | 點擊按鈕事件后的回調函數,用於得到數據並修改界面UI |
obj | 在哪個對象后創建分頁控件 |
count | 數據總數 |
totalPage | 一共有多少頁 |
showPageCount | 顯示多少個分頁按鈕 |
first | 分頁控件從第幾頁開始顯示 |
last | 分頁控件顯示到第幾頁 |
這些屬性中,
totalPage是計算出來的,它等於數據總數除以每頁的數據量,如果不能整除還需要加1。
showPageCount是計算出來的,它如果比totalPage還大,值就為totalPage,否則就等於傳進來的參數。
first是分頁控件中最左邊的按鈕的值,初始為1。
last是分頁控件中最左邊的值,初始為showPageCount。
在分頁控件不斷地變化中,其實真正改變的只是first,last和nowPage這三個屬性。
下面一起來看一下分頁控件的產生過程
1 /* 2 * 創建分頁控件 3 */ 4 o.createPage = function() 5 { 6 //拼接分頁控件 7 var html = "<div class = 'page-div'><div class = 'my-page'>"; 8 for(var i = 0 ; i < o.showPageCount ; i++) 9 { 10 //拼接每一個分頁數組按鈕,並為其設置id 11 html += "<a href='#' id=page"+(i+1)+" class = 'page-item each-page'>"+(i+1)+"</a>"; 12 } 13 //拼接下一頁按鈕 14 html += "<a href='#' class = 'page-item next-page'>>></a></div></div>"; 15 //在指定的對象后創建控件 16 o.obj.after(html); 17 $("#page1").css("background-color","gray"); 18 //調用獲取數據的回調函數 19 o.getData(o.nowPage, o.listRow); 20 }
從代碼中可以看出,Page對象有一個createPage方法,它通過組裝html來實現創建分頁控件,同時,第16行是在指定的jquery對象后面添加該元素,17行是讓默認第一個按鈕為被選中的加深背景顏色,最后調用回調函數getData來獲得分頁控件所控制的第一次的數據。
注意getData中有兩個參數,傳的分別是當前的頁數和每一頁多少行數據,相信用過分頁的人都知道,這兩個參數到后台是為了用limit來限制數據庫查詢的。
創建后接下來我們要為創建的元素來綁定事件,代碼如下:
1 /* 2 * 為控件綁定點擊事件 3 */ 4 o.bindAction = function() 5 { 6 $(".pre-page").click(function(){ 7 o.nowPage = parseInt(o.nowPage) - 1; 8 if(o.nowPage < (o.totalPage-o.showPageCount/2) && o.first > 1) 9 { 10 o.first = parseInt(o.first) - 1; 11 o.last = parseInt(o.last) - 1; 12 } 13 o.updatePage(); 14 o.updateColor($(this),$("#page"+ o.nowPage)); 15 o.getData(o.nowPage, o.listRow); 16 }); 17 18 $(".each-page").click(function(){ 19 o.nowPage = $(this).text(); 20 if(o.nowPage >= o.showPageCount/2+1 && o.nowPage <= (o.totalPage - o.showPageCount/2)) 21 { 22 if(o.showPageCount%2 == 0) 23 { 24 o.first = parseInt(o.nowPage)-parseInt(o.showPageCount/2-1); 25 o.last = parseInt(o.nowPage)+parseInt(o.showPageCount/2); 26 } 27 else 28 { 29 o.first = parseInt(o.nowPage)-parseInt(o.showPageCount/2); 30 o.last = parseInt(o.nowPage)+parseInt(o.showPageCount/2); 31 } 32 } 33 else if(o.nowPage < o.showPageCount/2) 34 { 35 o.first = 1; 36 o.last = o.showPageCount; 37 } 38 else if(o.nowPage > (o.totalPage - o.showPageCount/2)) 39 { 40 o.first = parseInt(o.totalPage) - parseInt(o.showPageCount)+1; 41 o.last = parseInt(o.totalPage); 42 } 43 o.updatePage(); 44 o.updateColor($(this),$("#page"+ o.nowPage)); 45 o.getData(o.nowPage, o.listRow); 46 }); 47 48 $(".next-page").click(function(){ 49 o.nowPage = parseInt(o.nowPage) + 1; 50 if(o.last < o.totalPage && o.nowPage > o.showPageCount/2+1) 51 { 52 o.first = parseInt(o.first) + 1; 53 o.last = parseInt(o.last) + 1; 54 } 55 o.updatePage(); 56 o.updateColor($(this),$("#page"+ o.nowPage)); 57 o.getData(o.nowPage, o.listRow); 58 }); 59 }
其實這里主要是為三類按鈕綁定事件,分別是pre-page、each-page和next-page,對應的按鈕分別是,前一頁,中間的數字按鈕和后一頁。
首先要先為大家說明一點的是,分頁的居中問題,用過分頁的我們都應該知道,分頁如果不是在選擇的頁數不是最靠近第一頁或者靠近最后一頁,那么當前的選擇項應該是默認在中間的。這樣說可能大家也不是很清楚,我拿baidu的分頁給大家舉例說明:
首先我們先選中第一頁來看效果:
可以看到選擇第一頁的時候是沒有前一頁的按鈕的。
接下來我們點擊第二頁看看:
可以看到,上一頁出現了,但是2這個按鈕並沒有居中顯示,因為它的左邊只有1並且1已經顯示出來了。
點擊7看看結果:
可以看大,7居中顯示了,因為它的左邊即顯示不到1,右邊也顯示不到16(共16頁)
我們在點擊15看看效果:
可以看出來該結果一共是16頁的,所以當點擊15的時候因為右邊最大顯示的是16,所以15也沒有居中顯示
同樣的當我們點擊16的時候下一頁的按鈕會消失。
相信說道這里,大家對於分頁已經有一個簡單的認識了,那么接下來,我們看看該如何去判斷這些問題。
其實前面也說了,判斷這些界限問題,主要就是根據first、last和nowPage來改變分頁狀態的,nowPage是我們直接改變的,first和last是根據nowPage而間接進行改變的。
第6~16行處理的是點擊前一頁時所觸發的事件。首先讓當前頁數-1,正常來講此時我們應該讓firstPage和lastPage都-1來保證能夠顯示到更前面的一些頁面。但是我們需要考慮到上面說的居中問題,所以我們需要先進行一個判斷,如果當前的頁面是小於 totalPage-showPageCount/2(這樣判斷就可以保證在最右邊如果接近了最大頁數可以不再去改變first和last的值),同時也要保證,first是大於1的,如果等於1了肯定就不會在first和last的值肯定就不會改變了,那么就可以是first和last-1,屬性修改之后,第13~15行分別是重新生成分頁元素,修改被選中項的背景,然后重新請求數據。(這三個方法后面會講到)
第18~46行處理的是點擊每一個分頁按鈕所觸發的事件。首先讓當前頁數為所點擊的按鈕的頁數,然后需要判斷nowPage,先判斷如果
nowPage >= o.showPageCount/2+1 && o.nowPage <= (o.totalPage - o.showPageCount/2)
也就是說如果是nowPage即不靠近左邊的1,也不靠近最大頁數,那么就應該讓當前選中的頁居中顯示。所以first和last就應該分別設置到nowPage兩端,在設置之前還要先判斷,如果按鈕個數是偶數個的話,是不可能讓被選中的按鈕在正中間的,所以需要設置
o.first = parseInt(o.nowPage)-parseInt(o.showPageCount/2-1);
o.last = parseInt(o.nowPage)+parseInt(o.showPageCount/2);
如果是奇數個就可以在正中間,那么就設置為
o.first = parseInt(o.nowPage)-parseInt(o.showPageCount/2);
o.last = parseInt(o.nowPage)+parseInt(o.showPageCount/2);
接下來就需要判斷,如果nowPage是小於showPageCount/2的,也就是說是靠近1的,此時first和last就應該保持不變,first就是1,last就是showPageCount的值。
如果nowPage是大於totalPage-showPageCount/2的,也就是說是靠近totalPage的,此時first就是totalPage-showPageCount/2+1,last就是totalPage。
然后和上面一樣調用重新生成分頁元素,修改被選中項的背景和重新請求數據的方法。
第48~57行和第一類思路是一樣的,只不過判斷的是last的臨界,這里就不再螯述了。
下面看另外一個方法:
1 /* 2 * 更新分頁控件 3 */ 4 o.updatePage = function() 5 { 6 //根據當前頁判斷重新拼接分頁控件 7 var html = ""; 8 if(o.nowPage != 1) 9 { 10 html += "<a href='#' class = 'page-item pre-page'><<</a>"; 11 } 12 for(var i = o.first ; i <= o.last ; i++) 13 { 14 html += "<a href='#' id=page"+i+" class = 'page-item each-page'>"+i+"</a>"; 15 } 16 if(o.nowPage != o.totalPage) 17 { 18 html+="<a href='#' class = 'page-item next-page'>>></a>"; 19 } 20 $(".my-page").html(html); 21 o.bindAction(); 22 }
該方法是更新分頁控件的方法,根據nowPage、first和last來更新,
首先判斷如果nowPage不是第一頁,那么就加上‘上一頁’的按鈕。
然后根據first和last來循環添加中間的數字按鈕。
接下來如果nowPage不是最后一頁,那么就加上'下一頁'的按鈕。
最后為新生成的元素綁定事件。
1 /** 2 * 顯示分頁空間 3 */ 4 o.show = function() 5 { 6 o.delete(); 7 o.createPage(); 8 o.bindAction(); 9 } 10 /* 11 * 更新控件顏色 12 */ 13 o.updateColor = function(self,obj) 14 { 15 //將所有的分頁按鈕背景顏色設為白色 16 self.parent().find('a').css("background-color","white"); 17 //將選中的按鈕背景設為灰色 18 obj.css("background-color","gray"); 19 } 20 /* 21 * 刪除控件 22 */ 23 o.delete = function() 24 { 25 $(".page-div").html(" "); 26 }
最后三個方法放在一起說了。
首先說下更新控件顏色,傳的參數一個是觸發事件的對象,另一個是需要設置為選中狀態的對象,分別改變他們的顏色。
顯示分頁控件很簡單,實際上就是刪除原有的分頁,創建新的分頁最后綁定事件。寫該方法是因為有時候我們操作數據會改變數據的個數,此時我們就需要重新創建一個分頁對象,就需要調用該方法。
說了這么多接下來就說說用法
用法很簡單
1 var searchTable = function(nowPage,listRows) 2 { 3 var url = $("#search").attr("url"); 4 var startTime = $("#startTime").val(); 5 var endTime = $("#endTime").val(); 6 var realname = $("#realname").val(); 7 var mode = 0; 8 if($("#user_mode").attr("value") == 1) 9 mode = 1; 10 else 11 mode = 2; 12 $.ajax({ 13 type:"post", 14 url:url, 15 data:{"startTime":startTime,"endTime":endTime,"real_name":realname,"mode":mode,"now_page":nowPage,"list_rows":listRows}, 16 success:function(data) 17 { 18 if(data == 0) 19 { 20 alert("暫無符合要求數據"); 21 } 22 else 23 { 24 data = JSON.parse(data); 25 removeDataRow(); 26 addNewData(data); 27 } 28 }, 29 error:function() 30 { 31 alert("查詢失敗"); 32 } 33 }); 34 }
首先定義了取數據的回調函數。
1 var url = $("#data-count").attr("value"); 2 $.ajax({ 3 url: url, 4 type:"post", 5 success:function(result) 6 { 7 var page = new Page(result,1,10,$("#data-table"),searchTable); 8 page.show(); 9 } 10 , 11 error:function() 12 { 13 alert("路徑錯誤"); 14 } 15 });
然后得到數據總數,並創建分頁即可,實際上就
var page = new Page(result,1,10,$("#data-table"),initTable);
page.show();
這兩句是我們分頁類有關的代碼,剩下的都是為我們的參數所准備的代碼。
這里說一下,如果我們想要動態的修改表格數據,是需要重新生成分頁類的,也就是說需要重新得到正確的參數來構造分頁對象。
最后附上源碼供大家參考(樣式表大家可以定制自己喜歡的,這里我就不再傳了):

1 /** 2 * Created by gy on 15/4/19. 3 */ 4 5 function Page(count,listRow,showPageCount,obj,getData){ 6 var o = {};//分頁對象 7 o.nowPage = 1;//當前為第幾頁 8 o.listRow = listRow;//一頁顯示多少條數據 9 o.getData = getData;//取數據的回調函數 10 o.obj = obj;//制定在那個元素后面顯示(Jquery對象) 11 o.count = count;//數據總數 12 //總頁數 13 o.totalPage = o.count% o.listRow == 0? parseInt(o.count/ o.listRow) : parseInt(o.count/ o.listRow+1); 14 //顯示多少個分頁按鈕 15 o.showPageCount = o.showPageCount < o.totalPage? o.showPageCount : o.totalPage; 16 o.first = 1;//第一個顯示的分頁按鈕是多少 17 //最后一個顯示的分頁按鈕是多少 18 o.last = o.totalPage > showPageCount?showPageCount: o.totalPage; 19 20 /** 21 * 顯示分頁空間 22 */ 23 o.show = function() 24 { 25 o.delete(); 26 o.createPage(); 27 o.bindAction(); 28 } 29 30 /* 31 * 創建分頁控件 32 */ 33 o.createPage = function() 34 { 35 //拼接分頁控件 36 var html = "<div class = 'page-div'><div class = 'my-page'>"; 37 for(var i = 0 ; i < o.showPageCount ; i++) 38 { 39 //拼接每一個分頁數組按鈕,並為其設置id 40 html += "<a href='#' id=page"+(i+1)+" class = 'page-item each-page'>"+(i+1)+"</a>"; 41 } 42 //拼接下一頁按鈕 43 html += "<a href='#' class = 'page-item next-page'>>></a></div></div>"; 44 //在指定的對象后創建控件 45 o.obj.after(html); 46 $("#page1").css("background-color","gray"); 47 //調用獲取數據的回調函數 48 o.getData(o.nowPage, o.listRow); 49 } 50 /* 51 * 更新分頁控件 52 */ 53 o.updatePage = function() 54 { 55 //根據當前頁判斷重新拼接分頁控件 56 var html = ""; 57 if(o.nowPage != 1) 58 { 59 html += "<a href='#' class = 'page-item pre-page'><<</a>"; 60 } 61 for(var i = o.first ; i <= o.last ; i++) 62 { 63 html += "<a href='#' id=page"+i+" class = 'page-item each-page'>"+i+"</a>"; 64 } 65 if(o.nowPage != o.totalPage) 66 { 67 html+="<a href='#' class = 'page-item next-page'>>></a>"; 68 } 69 $(".my-page").html(html); 70 o.bindAction(); 71 } 72 /* 73 * 更新控件顏色 74 */ 75 o.updateColor = function(self,obj) 76 { 77 //將所有的分頁按鈕背景顏色設為白色 78 self.parent().find('a').css("background-color","white"); 79 //將選中的按鈕背景設為灰色 80 obj.css("background-color","gray"); 81 } 82 /* 83 * 刪除控件 84 */ 85 o.delete = function() 86 { 87 $(".page-div").html(" "); 88 } 89 /* 90 * 為控件綁定點擊事件 91 */ 92 o.bindAction = function() 93 { 94 $(".pre-page").click(function(){ 95 o.nowPage = parseInt(o.nowPage) - 1; 96 if(o.nowPage < (o.totalPage-o.showPageCount/2) && o.first > 1) 97 { 98 o.first = parseInt(o.first) - 1; 99 o.last = parseInt(o.last) - 1; 100 } 101 o.updatePage(); 102 o.updateColor($(this),$("#page"+ o.nowPage)); 103 o.getData(o.nowPage, o.listRow); 104 }); 105 106 $(".each-page").click(function(){ 107 o.nowPage = $(this).text(); 108 if(o.nowPage >= o.showPageCount/2+1 && o.nowPage <= (o.totalPage - o.showPageCount/2)) 109 { 110 if(o.showPageCount%2 == 0) 111 { 112 o.first = parseInt(o.nowPage)-parseInt(o.showPageCount/2-1); 113 o.last = parseInt(o.nowPage)+parseInt(o.showPageCount/2); 114 } 115 else 116 { 117 o.first = parseInt(o.nowPage)-parseInt(o.showPageCount/2); 118 o.last = parseInt(o.nowPage)+parseInt(o.showPageCount/2); 119 } 120 } 121 else if(o.nowPage < o.showPageCount/2) 122 { 123 o.first = 1; 124 o.last = o.showPageCount; 125 } 126 else if(o.nowPage > (o.totalPage - o.showPageCount/2)) 127 { 128 o.first = parseInt(o.totalPage) - parseInt(o.showPageCount)+1; 129 o.last = parseInt(o.totalPage); 130 } 131 o.updatePage(); 132 o.updateColor($(this),$("#page"+ o.nowPage)); 133 o.getData(o.nowPage, o.listRow); 134 }); 135 136 $(".next-page").click(function(){ 137 o.nowPage = parseInt(o.nowPage) + 1; 138 if(o.last < o.totalPage && o.nowPage > o.showPageCount/2+1) 139 { 140 o.first = parseInt(o.first) + 1; 141 o.last = parseInt(o.last) + 1; 142 } 143 o.updatePage(); 144 o.updateColor($(this),$("#page"+ o.nowPage)); 145 o.getData(o.nowPage, o.listRow); 146 }); 147 } 148 return o; 149 }