目標
制作js分頁導航jq插件,用於無刷新分頁或者刷新分頁
實現目標參考京東和天貓的分頁條.
有四個固定按鈕,前頁碼,后頁碼,首頁,末頁.
程序關鍵點在於計算中間頁面的起止位置.邏輯是以當前頁碼為參照點,根據需要顯示的頁碼按鈕個數,計算參照點前后的頁碼數量.
當起止點小於1或者大於最大頁碼時,需要調整起點為1,或止點為最大頁碼.
效果圖
html結構
容器nav,里面分為頁碼區(pagenum-btns)和跳轉區(pagenum-skip)兩部分.
js生成nav里面的內容.
<nav class="pagenum" id="pagenum1"> <span class="pagenum-btns"> <a class="pagenum-prev"><</a> <a class="pagenum-num">1</a> <span class="pagenum-break">...</span> <a class="pagenum-num">7</a> <a class="pagenum-num">8</a> <a class="pagenum-active">9</a> <a class="pagenum-num">10</a> <a class="pagenum-num">11</a> <span class="pagenum-break">...</span> <a class="pagenum-num">98</a> <a class="pagenum-next">></a> </span> <span class="pagenum-skip"> 共<b class="pagenum-total">98</b>頁 到第<input class="pagenum-input" value="1" type="text" />頁<a class="pagenum-ok">確定</a> </span> </nav>
調用
// dom結構 需要一個容器
// 將相應樣式添加到容器可調整外觀.大小: sm lg xl 顏色: gray red green yellow 位置:center right
<nav class="pagenum" id="pagenumId"></nav> // 調用方法 let cfg={ // 點擊頁碼方法(必須) pageClickE:function(){}, // 總數(必須) >0 totalData:100, // 當前頁碼(必須) >0 pageIndex:'當前頁碼', // 每頁數量 [5-50] pageSize:10, // 顯示幾個按鈕[5-10] totalBtn:5 } $('#pagenumId').pagenum(cfg);
web前端一般是無刷新分頁,pageClickE方法會包含一個ajax請求,這個請求的回調方法里,再執行生成新的分頁條,並且配置參數中的pageClickE,再次指向ajax方法自己
// ajax請求示例方法 function getdata() { var para = {}; $.post('/api/PageNumber', { para:JSON.stringify(para) }, function (data) { if (data.length == 0) { // 如果沒有數據返回,可以不用生成分頁條. return; } // 再生成新分頁條 let cfg= { // 這里綁定getdata方法自己 pageClickE:function(){ getdata() }, // 總數(必須) >0 由后端返回新的總數 totalData:data.總數, // 當前頁碼(必須) >0 由后端返回當前頁碼,或者頁面記住當前請求頁面 pageIndex:data.當前頁碼, // 每頁數量 [5-50] pageSize:10, // 顯示幾個按鈕[5-10] totalBtn:5 } $('#pagenumId').pagenum(cfg); }

.pagenum { height: 2.7em; line-height: 2.7em; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; } .pagenum-btns { font-size: 0; } .pagenum-prev, .pagenum-num, .pagenum-active, .pagenum-next, .pagenum-break { display: inline-block; width: 2.7em; text-align: center; font-size: 14px; color: #007bff; border: 1px solid #ced4da; border-left: none; } .pagenum-prev:hover, .pagenum-num:hover, .pagenum-active:hover, .pagenum-next:hover { text-decoration: none; cursor: pointer; color: #007bff; background-color: #e9ecef; } .pagenum-prev { border-left: 1px solid #ced4da; } .pagenum-active, .pagenum-active:hover { color: #fff; background-color: #007bff; } .pagenum-break { color: #ced4da; } .pagenum-skip { margin-left: 5px; } .pagenum-input { width: 2.7em; text-align: center; border: 1px solid #ced4da; padding: 0; margin: 0 3px; } .pagenum-input:focus { outline: 2px solid #007bff; } .pagenum-ok { display: inline-block; width: 3em; text-align: center; margin-left: 5px; color: #007bff; border: 1px solid #ced4da; } .pagenum-ok:hover { text-decoration: none; color: #007bff; cursor: pointer; } .pagenum.sm { font-size: 12px; } .pagenum.sm .pagenum-prev, .pagenum.sm .pagenum-num, .pagenum.sm .pagenum-active, .pagenum.sm .pagenum-next, .pagenum.sm .pagenum-break { font-size: 12px; } .pagenum.lg { font-size: 16px; } .pagenum.lg .pagenum-prev, .pagenum.lg .pagenum-num, .pagenum.lg .pagenum-active, .pagenum.lg .pagenum-next, .pagenum.lg .pagenum-break { font-size: 16px; } .pagenum.xl { font-size: 20px; } .pagenum.xl .pagenum-prev, .pagenum.xl .pagenum-num, .pagenum.xl .pagenum-active, .pagenum.xl .pagenum-next, .pagenum.xl .pagenum-break { font-size: 20px; } .pagenum.gray .pagenum-prev, .pagenum.gray .pagenum-num, .pagenum.gray .pagenum-active, .pagenum.gray .pagenum-next, .pagenum.gray .pagenum-break, .pagenum.gray .pagenum-prev:hover, .pagenum.gray .pagenum-num:hover, .pagenum.gray .pagenum-active:hover, .pagenum.gray .pagenum-next:hover, .pagenum.gray .pagenum-ok, .pagenum.gray .pagenum-ok:hover { color: #6c757d; } .pagenum.gray .pagenum-active, .pagenum.gray .pagenum-active:hover { color: #fff; background-color: #6c757d; } .pagenum.green .pagenum-prev, .pagenum.green .pagenum-num, .pagenum.green .pagenum-active, .pagenum.green .pagenum-next, .pagenum.green .pagenum-break, .pagenum.green .pagenum-prev:hover, .pagenum.green .pagenum-num:hover, .pagenum.green .pagenum-active:hover, .pagenum.green .pagenum-next:hover, .pagenum.green .pagenum-ok, .pagenum.green .pagenum-ok:hover { color: #28a745; } .pagenum.green .pagenum-active, .pagenum.green .pagenum-active:hover { color: #fff; background-color: #28a745; } .pagenum.red .pagenum-prev, .pagenum.red .pagenum-num, .pagenum.red .pagenum-active, .pagenum.red .pagenum-next, .pagenum.red .pagenum-break, .pagenum.red .pagenum-prev:hover, .pagenum.red .pagenum-num:hover, .pagenum.red .pagenum-active:hover, .pagenum.red .pagenum-next:hover, .pagenum.red .pagenum-ok, .pagenum.red .pagenum-ok:hover { color: #dc3545; } .pagenum.red .pagenum-active, .pagenum.red .pagenum-active:hover { color: #fff; background-color: #dc3545; } .pagenum.yellow .pagenum-prev, .pagenum.yellow .pagenum-num, .pagenum.yellow .pagenum-active, .pagenum.yellow .pagenum-next, .pagenum.yellow .pagenum-break, .pagenum.yellow .pagenum-prev:hover, .pagenum.yellow .pagenum-num:hover, .pagenum.yellow .pagenum-active:hover, .pagenum.yellow .pagenum-next:hover, .pagenum.yellow .pagenum-ok, .pagenum.yellow .pagenum-ok:hover { color: #ffc107; } .pagenum.yellow .pagenum-active, .pagenum.yellow .pagenum-active:hover { color: #fff; background-color: #ffc107; } .pagenum.center { text-align: center; } .pagenum.right { text-align: right; }

$.fn.extend({ /*=============================================================================* * 調用 $('#pagenum1').pagenum(cfg), 每次調用都會更新分頁條狀態. * 必須參數:{totalData:'總數',pageIndex:'當前頁碼',pageSize:'每頁數量'} * 當總數大於0時,才需要調用分頁條 *=============================================================================*/ pagenum: function (config) { // 外層框JQ對象 let pnJQ = $(this); let cfg = {}; /*====================* * 方法 public *====================*/ /*====================* * 方法 private *====================*/ // 初始化配置 {totalData:'總數',pageIndex:'當前頁碼',pageSize:'每頁數量',pageClickE:'點擊頁碼方法'} let initCfg = function (config) { // 當前頁碼 cfg.PageIndex = config.pageIndex || 1; // 每頁數量[5-50] cfg.PageSize = (config.pageSize > 4 && config.pageSize < 51) ? config.PageSize : 10; // 數據總數 cfg.TotalData = config.totalData || 0; // 總頁數 cfg.TotalPage = getTotalPage(); // 分頁按鈕個數[5-10]. cfg.TotalBtn = (config.totalBtn > 4 && config.pageSize < 11) ? config.totalBtn : 5; // 頁碼點擊事件方法 cfg.pageClickE = config.pageClickE; } // 主要方法:更新分頁條數據,綁定相關事件 let newPageNum = function () { // 清空DOM,重新生成分頁組件DOM,綁定事件 pnJQ.empty(); // 1.頁碼按鈕區域 pnJQ.append('<span class="pagenum-btns"></span>'); // 2.跳轉按鈕區域 pnJQ.append(String.Format('<span class="pagenum-skip">共<b class="pagenum-total">{0}</b>頁 到第<input class="pagenum-input" />頁<a class="pagenum-ok">確定</a></span>' , cfg.TotalPage)); // 計算頁碼起止 pagenumRange(); //console.log(cfg); /*-------------------------------------------------------* * 添加按鈕DOM * 頁碼區固定按鈕4個:前一頁,第1頁和第末頁,后一頁. *-------------------------------------------------------*/ let btndom = ''; // 向前按鈕 btndom += String.Format('<a class="pagenum-prev" pagenum="{0}"><</a>', cfg.PageIndex - 1); // 第1頁按鈕,當起始頁碼大於1時添加 if (cfg.StartIndex > 1) btndom += String.Format('<a class="pagenum-{0}" pagenum="1">1</a>', cfg.PageIndex == 1 ? 'active' : 'num'); // 前省略號,當起始頁碼大於2時添加 if (cfg.StartIndex> 2) { btndom+='<span class="pagenum-break">...</span>'; } // 頁碼按鈕 for (let i = cfg.StartIndex; i <= cfg.EndIndex; i++) { let pagenum = i; btndom += String.Format('<a class="pagenum-{0}" pagenum="{1}">{1}</a>' , pagenum == cfg.PageIndex ? 'active' : 'num', pagenum); } // 后省略號,當結束頁小於最大頁碼-1時 if (cfg.EndIndex < (cfg.TotalPage - 1)) { btndom+='<span class="pagenum-break">...</span>'; } // 末頁按鈕,當結束頁小於最大頁碼時添加 if (cfg.EndIndex < cfg.TotalPage) btndom += String.Format('<a class="pagenum-{0}" pagenum="{1}">{1}</a>', cfg.PageIndex == cfg.TotalPage ? 'active' : 'num', cfg.TotalPage); // 向后按鈕 btndom += String.Format('<a class="pagenum-next" pagenum="{0}">></a>', cfg.PageIndex + 1); // 將btndom添加到頁碼按鈕區域容器 pnJQ.find('.pagenum-btns').append(btndom); // 綁定所有按鈕事件 bindEventForAllBtn(); } // 計算起始頁碼位置:以當前頁碼為中間位置,根據需要顯示的頁碼按鈕個數,計算當前頁碼之前和之后的頁碼數. // 當前頁碼在正中,如果顯示按鈕個數為偶數,則偏左.例如: "2 3 (4:當前頁碼在此) 5 6 7" let pagenumRange = function () { let startIndex = cfg.PageIndex - parseInt(cfg.TotalBtn / 2) + (cfg.TotalBtn % 2 == 0 ? 1 : 0); let endIndex = cfg.PageIndex + parseInt(cfg.TotalBtn / 2); // 起始頁小於1,說明當前頁碼位於正中時,前面頁碼數不夠了.應將第1頁為起始頁碼,而結束頁碼也應該重新計算 if (startIndex < 1) { startIndex = 1; // 根據要顯示的頁碼數計算結束頁碼,如果算出頁碼數大於總頁碼,則以總頁碼數為結束頁碼 endIndex = endIndex > cfg.TotalPage ? cfg.TotalPage : cfg.TotalBtn; } // 結束頁碼大於總頁碼,說明當前頁碼位於正中時,后面的頁碼數不夠.應將總頁碼數為終止頁碼,起始頁碼應重新計算 if (endIndex > cfg.TotalPage) { endIndex = cfg.TotalPage; // 根據要顯示的頁碼數計算起始頁碼,如果算出小於1,則以1為起始頁碼 startIndex = endIndex - cfg.TotalBtn + 1; if (startIndex < 1) startIndex = 1; } cfg.StartIndex = startIndex; cfg.EndIndex = endIndex; } // 表示前一頁碼(應由當前頁碼計算得出) let getPrevPage = function () { return cfg.PageIndex == 1 ? 1 : cfg.PageIndex - 1; } // 表示后一頁碼 let getNextPage = function () { return cfg.TotalPage == cfg.PageIndex ? cfg.PageIndex : cfg.PageIndex + 1; } // 總頁數(由數量總數和分頁大小算出) let getTotalPage = function () { if (cfg.TotalData >= 0 && cfg.PageSize >= 5 && cfg.PageIndex >= 1) { let pagecount = parseInt(cfg.TotalData / cfg.PageSize); let pagecountM = cfg.TotalData % cfg.PageSize; return pagecountM > 0 ? pagecount + 1 : pagecount; } return 0; } /*====================* * 事件綁定 *====================*/ let bindEventForAllBtn = function () { // 頁碼按鈕點擊 pnJQ.find('.pagenum-prev,.pagenum-next,.pagenum-first,.pagenum-last,.pagenum-num').on('click', function () { // 頁碼參數范圍[1-總頁碼],范圍外不動作 let pnnum = parseInt($(this).attr('pagenum')) || 0; if (pnnum < 1 || pnnum > cfg.TotalPage) return; cfg.pageClickE(pnnum); }); // 確定按鈕點擊 pnJQ.find('.pagenum-ok').on('click', function () { let pnnum = parseInt(pnJQ.find('.pagenum-input').val()) || 0; if (pnnum < 1 || pnnum > cfg.TotalPage) return; cfg.pageClickE(pnnum); }); } /*============================* * 初始化配置,生成分頁組件 *============================*/ initCfg(config); newPageNum(); } })
代碼
https://github.com/mirrortom/webcoms/blob/master/mirrorui/js/pagenum.js