J2EE项目特别是后台管理,或者一部分前台展示数据比较多,通常需要分页把展示折叠在数据区内.
一般有几种方式来实现分页, 一是官方分页插件,二是自己写,三是网上找(类似于第一种)
这里就介绍第二种, 自写的分页器.
问题就是如果让数据折叠在数据区内, 一种方式是一次取回所有接口数据, 将分页逻辑写在前端, 这种方式相对简单,
且不会刷新页面, 只是考虑到一次数据太多, 会占用很多时间来传数据,生成DOM树,而且数据刷新比较滞后,一般不用.
第二种方式即是当下流行的方式, 将数据分页写在服务端,一次请求一页数据, 每次传页码页数,这样服务器每次返回一
页的数据供前端展示, 小巧灵活. 不便的是每次需要传页码和页数,频繁翻页会增加请求量.
接下来我就来分析一下分页的逻辑.
1. 先看效果
2. 主要功能: 点击页码处,提交请求页. 点击<和>上翻片和下翻片,附加功能是点击某片中最后一页,下翻片, 点击某片中第一页,上翻片.
3. 主要的障碍: 如何记录当前页, 如何分片, 如何共用分页器
主要的逻辑:服务器和客户端都需要增加逻辑, 服务器为数据列表型接口增加两个参数,page和pageSize, 指示当前页和页大小.
利用Hibernate中的listByPage来分页. 返回特定页的数据,注意数据是从第1页开始的.再将当前页和页大小传回到客户端.
客户端主要是提供一个表单来上传page和pageSize,通过点击页码来提交表单.获取Total后根据当前面和页大小生成当前片上的页码.
需要标记出当前分页器<和>的DOM位置,生成页码.
JS主要逻辑:
var allPageArray = new Array(); var pageArray = new Array(); var currentSlice = 1;// 当前片码 var currentPage = $('#pageHolder')[0].value;// 当前页码 var count = $('#countHolder')[0].value; // 总记录数 var initPageNum = 10; // 每片页码数量 var totalPage = Math.ceil(count / initPageNum);// 总页数 var pageUl = $('.pagination>ul')[0]; // 页码父结点 var pageNextPlace = $('li.next')[0]; // 下一片码对象 var pagePrevPlace = $('li.previous')[0]; // 上一片码对象 var lastPageTips = $('.lastPageTips')[0]; //最后一页提示DOM clearPage(); //清空页码 initAllPageArray();//初始化 function initAllPageArray() { for (var i = 0; i < totalPage; i++) { // 填充totalPage内容 allPageArray[i] = i; } if (totalPage >= initPageNum) { // 如果大于10页,装载当前面所在页片上的页码 if (currentPage == totalPage) { // 如果已经到达最后一页 pageArray = allPageArray.slice(currentPage - initPageNum, currentPage); tipLastPage(); } else { pageArray = allPageArray.slice(currentPage - currentPage % initPageNum, currentPage - currentPage % initPageNum + initPageNum > totalPage ? totalPage : currentPage - currentPage % initPageNum + initPageNum); } } else { pageArray = allPageArray;// 如果少于10页,全部展示 if (currentPage == totalPage) { if (totalPage != 1) { tipLastPage(); } } } loadPage(pageArray); // 装载页码 $('.pagination-style>ul>li>a').each(function() { // 激活当前页码样式 if (this.innerHTML == currentPage) { this.parentNode.className = "active"; } }); } // 取上/下翻页码数组 function getPageArray(pageArray, direct) { if (allPageArray.length != 0 && pageArray.length != allPageArray.length) { // 如果长度不相等则说明长度够几片 if (direct == 0) {// 前翻 if (pageArray[pageArray.length - 1] >= initPageNum) { // 从11页以后往前翻,前进10页 if (pageArray[0] >= initPageNum) {// 首页大于10页,则取前10页 pageArray = allPageArray.slice(pageArray[0] - initPageNum, pageArray[0]); } else {// 首页小于10,取上一页可能不满10页,则显示0-9页 pageArray = allPageArray.slice(0, initPageNum); } } else {// 从1-10页往前翻.装1-10 // 页码不需要加载 } } else if (direct == 1) {// 后翻 if (pageArray.length < 10 || (pageArray.length == 10 && pageArray[pageArray.length - 1] == allPageArray.length - 1)) {// 最后一片没装满或者最后一页装的是最后一片 // 不需要处理 pageArray = pageArray; tipLastPage(); } else { if (allPageArray.length >= (pageArray[pageArray.length - 1] + 10)) {// 最后还有一片可以装满 pageArray = allPageArray.slice( pageArray[pageArray.length - 1] + 1, pageArray[pageArray.length - 1] + 1 + initPageNum); } else {// 最后一片,装不满 pageArray = allPageArray.slice( pageArray[pageArray.length - 1] + 1, allPageArray.length); } } } } else {// 如果长度不够10,说明一片都没存满 pageArray = allPageArray; } return pageArray; } // 加载页码DOM function loadPage(array) {// 加载一片页码 var pageUl = $('.pagination>ul')[0]; var pageNextPlace = $('li.next')[0]; var num = initPageNum; for (var i = 0; i < array.length; i++) { var pageNode = pageNextPlace.cloneNode(true);//克隆的是>下翻的DOM pageNode.className = "";//清空className, classList不适配所有的浏览器 var aLink = pageNode.querySelector("a"); aLink.innerHTML = array[i] + 1;//写上页码 aLink.className = ""; pageUl.insertBefore(pageNode, pageNextPlace); } initPageNodeClick(); } // 提交search form表单 $('input')[2].onblur = function() { $("[name='page']")[0].value = "1"; $('#searchForm')[0].submit(); } // $('input')[2].onfocus = function() { $("[name='page']")[0].value = "1"; } // 初始化页片上页码的点击响应功能 function initPageNodeClick() { $('.pagination-style>ul>li>a') .each( function() { this.onclick = function() { if (this.className == "fui-arrow-left") { if (totalPage <= 10) { if (undefined == $('.pagination-style>ul>li>a')[1].click) { dispatch( $('.pagination-style>ul>li>a')[1], "click"); // safari } else { $('.pagination-style>ul>li>a')[1] .click(); } ; } else { pagePrevClick(); } } else if (this.className == "fui-arrow-right") { if (totalPage <= 10) { if (undefined == pageUl .querySelectorAll('li')[totalPage] .querySelector('a').click) { dispatch( pageUl.querySelectorAll('li')[totalPage] .querySelector('a'), "click"); // safari } else { pageUl.querySelectorAll('li')[totalPage] .querySelector('a').click(); } } else { pageNextClick(); } } else { $("[name='page']")[0].value = this.innerHTML; $('#searchForm')[0].submit(); } }; }) } // 清空页码DOM function clearPage() { var liArray = $('.pagination-style>ul>li'); for (var i = 0; i < liArray.length; i++) { var li = liArray[i]; if (li.className != 'previous' && li.className != 'next') { pageUl.removeChild(li); } } } // 上翻页片功能 function pagePrevClick() { clearPage(); pageArray = getPageArray(pageArray, 0); loadPage(pageArray); } // 下翻页片功能 function pageNextClick() { var temp = getPageArray(pageArray, 1); if (pageArray != temp) { pageArray = temp; clearPage(); loadPage(pageArray); } } function tipLastPage() { $(lastPageTips).css("visibility", "visible"); clearTips(); } function clearTips() { setTimeout(function() { $(lastPageTips).css("visibility", "hidden"); }, 1500); } //为了适配Safari,点击a标签不会触发onclick事件. function dispatch(el, type) { try { var evt = document.createEvent('Event'); evt.initEvent(type, true, true); el.dispatchEvent(evt); } catch (e) { alert(e); } }