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);
}
}