段时候写IM即时通讯的时候,要对用户的聊天记录进行分页,于是就写了一个对聊天记录进行分页的公告函数,嗯,的确很好用!
eg:
首先要考虑这个对数组进行分页的函数要接收的参数,在此我的是:
function pagination (pageNo, pageSize, origin) { }
有了这三个参数,我们已经可以实现数组分页了,再此我主要使用的是 JS 数组的 slice 方法,因为 splice 的话,会改变原数组。
slice() 方法可从已有的数组中返回选定的元素。
语法
arrayObject.slice(start,end)
首先我们需要确定切片的起始位置,因为是从0开始,所以需要减1,然后用得到的结果乘以pageSize每页数量就可以得到分页的起始位置。
得到了 pageSize 之后,我们只需要得到 end 切片终止位置即可。
用起始位置加上pageSize就可以得到。
function pagination (pageNo, pageSize, origin) { // 获取切片的起始位置 const originSection=(pageNo - 1) * pageSize const currentPage=origin.slice(originSection, originSection + pageSize) }
PS: 如果要切的起始位置大于当前数组的总长度,是切不到的,只会得到空数组,所以我们不需要做多余处理。
核心已经实现了,接下来稍微完善一下即可;我们可以把总页数,总长度等一并返回:
源码;
开发过程中,经常做的一件事,也是最基本的事,就是从数据库中查询数据,然后在客户端显示出来。当数据少时,可以在一个页面内显示完成。然而,如果查询记录是几百条、上千条呢?直接一个页面显示完全的话,表格得多长啊。。。。。。这时,我们可以用分页技术。
何为分页?效果图如下:
这里总共查询了100条记录,如果一次性显示的话表格会很多行,用户体验不佳。而我们采用分页显示的话,一页显示10条记录,共十页。用户可以自行翻阅,记录少,清晰显示。
下面谈谈分页效果的实现,思路有三种:
其一:纯JS实现分页。一次性查询记录并加载到html的table中。然后通过选择性地显示某些行来达到分页显示的目的。这是一种伪分页,障眼法而已。只能用于数据少的情况下。一旦数据多了,十几万条数据加载到html中会变得很慢。而且不实时,一次加载完后数据就写死在页面了,若数据库中有变化,浏览器端显示的仍是上次加载过来的数据。
首先:用table来显示查询出来的记录们,全部显示。
<table width="500" id="idData">
<%
String user_id, user_name, user_sex, user_phone, user_age;
while (sqlRst.next()) {
user_id=sqlRst.getString(1);
user_name=sqlRst.getString(2);
user_sex=sqlRst.getString(3);
user_phone=sqlRst.getString(4);
user_age=sqlRst.getString(5);
%>
<tr>
<td><%=user_id%></td>
<td><%=user_name%></td>
<td><%=user_sex%></td>
<td><%=user_phone%></td>
<td><%=user_age%></td>
</tr>
<%
}
%>
</table>
<br/>
<table width="60%" align="right">
<tr><td><div id="changePages" name="changePages"></div></td></tr>
</table>
然后,在JS中修改table中某些行显示,某些行隐藏。
<script type="text/javascript">
function goPage(pno,psize){
var itable=document.getElementById("idData");//获取table
var num=itable.rows.length;//得到记录总数
var totalPage=0;
var pageSize=psize;//一页显示pageSize条记录
//计算总页数
if(num/pageSize > parseInt(num/pageSize)){
totalPage=parseInt(num/pageSize)+1;
}else{
totalPage=parseInt(num/pageSize);
}
//当前页数
var currentPage=pno;
//获取当前页第一条、最后一条记录的行号
var startRow=(currentPage - 1) * pageSize+1;
var endRow=currentPage * pageSize;
endRow=(endRow > num)? num : endRow;
//修改table中当前页对应的行的属性为显示,非本页的记录为隐藏
for(var i=1;i<(num+1);i++){
var irow=itable.rows[i-1];
if(i>=startRow && i<=endRow){
irow.style.display="block";
}else{
irow.style.display="none";
}
}
//分页页码列表
var tempStr="共"+num+"条记录 分"+totalPage+"页 当前第"+currentPage+"页";
if(currentPage>1){
tempStr +="<a href=\"#\" onClick=\"goPage("+(1)+","+psize+")\">首页</a>";
tempStr +="<a href=\"#\" onClick=\"goPage("+(currentPage-1)+","+psize+")\"><上一页</a>"
}else{
tempStr +="首页";
tempStr +="<上一页";
}
if(currentPage<totalPage){
tempStr +="<a href=\"#\" onClick=\"goPage("+(currentPage+1)+","+psize+")\">下一页></a>";
tempStr +="<a href=\"#\" onClick=\"goPage("+(totalPage)+","+psize+")\">尾页</a>";
}else{
tempStr +="下一页>";
tempStr +="尾页";
}
document.getElementById("changePages").innerHTML=tempStr;
}
</script>
其二:一次查询,分批显示。
就是说,我们可以执行一个数据库查询操作,得到结果集rs。然后,通过指针的移动来显示当前页面的记录。这样,就可以以 rs.absolute(当前页面号*每页记录数)定位到当前页的第一条记录,然后通过while循环显示n条记录(n为每页显示记录数)。在跳页时,只需修改currentPage,即可在重定位到下一页时把当前页面号改掉,重新定位记录指针,通过while遍历显示n条记录。与JS选择性显示不同,这里是选择性遍历。与JS分页不同的是,这里分页每次跳页修改的是遍历的指针,每次跳页都要进行一次全面查询。同样地,不适合大数据量查询。这里比JS分页优化的地方在于——实时性。每次跳页都会查询一次数据库,保证数据的实时性。
参考代码:
<%
int intPageSize=10; //一页显示的记录数 int intRowCount; //记录总数
int intPageCount; //总页数
String strPage; //从表单或URL传送的待显示页码
int intPage; //待显示页码 ,由strPage转换成的整数
//---计算记录总数的第一种方法:查询出所有记录,移动结果集指针到最后一条,获取最后一条记录的行号
//查询所有数据 ResultSet sqlRst=sqlStmt.executeQuery("select * from user");
//获取记录总数
sqlRst.last(); //光标在最后一行
intRowCount=sqlRst.getRow(); //获得当前行号,即总记录数
//记算总页数
intPageCount=(int)Math.ceil(intRowCount/(intPageSize*1.0));
//将记录指针定位到待显示页的第一条记录上
sqlRst.absolute((intPage - 1) * intPageSize + 1);
//显示数据
int i=0;
String user_id, user_name, user_sex, user_phone, user_age;
while (i < intPageSize && !sqlRst.isAfterLast()) {
user_id=sqlRst.getString(1);
user_name=sqlRst.getString(2);
user_sex=sqlRst.getString(3);
user_phone=sqlRst.getString(4);
user_age=sqlRst.getString(5);
%>
<tr>
<td><%=user_id%></td>
<td><%=user_name%></td>
<td><%=user_sex%></td>
<td><%=user_phone%></td>
<td><%=user_age%></td>
</tr>
<%
sqlRst.next();//移动记录指针指向下一条记录
i++;//统计当前页已显示多少条记录
}
%>
其三:在服务端分页。跳到第n页才查询、显示第n页内容。要点就是根据客户端表格的“页面”计算出数据库要查询的当前页面的第一条记录的位置。优点:实时性:跳页才查询。数据量小:只加载当前页的记录进行显示。
重点在于两条语句:select count(*) from ...:查询得到记录总条数
select * from .. limit pageNo,rowsCount:查询从第pageNo条开始的rowsCount条数据。
int pages=0; //待显示页面
int count=0; //总条数
int totalpages=0; //总页数
int limit=10; //每页显示记录条数
//计算记录总数的第二种办法:使用mysql的聚集函数count(*)
ResultSet sqlRst=sqlStmt.executeQuery("select count(*) from user");
if(sqlRst.next()){
count=sqlRst.getInt(1);//结果为count(*)表,只有一列。这里通过列的下标索引(1)来获取值
}
//由记录总数除以每页记录数得出总页数
totalpages=(int)Math.ceil(count/(limit*1.0));
//获取跳页时传进来的当前页面参数
String strPage=request.getParameter("pages");
//判断当前页面参数的合法性并处理非法页号(为空则显示第一页,小于0则显示第一页,大于总页数则显示最后一页)
if (strPage==null) {
pages=1;
} else {
try{
pages=java.lang.Integer.parseInt(strPage);
}catch(Exception e){
pages=1;
}
if (pages < 1){
pages=1;
}
if (pages > totalpages){
pages=totalpages;
}
}
//由(pages-1)*limit算出当前页面第一条记录,由limit查询limit条记录。则得出当前页面的记录
sqlRst=sqlStmt.executeQuery("select * from user order by user_id limit " + (pages - 1) * limit + "," + limit);
while (sqlRst.next()){//遍历显示}
跳页的实现:跳页是通过重定向来实现的,通过向当前网页传进待显示的pages,在跳转后根据pages重新算出页面显示的第一条,查limit条显示。
<form name="f1" method="POST" action="index.jsp" onSubmit="return checknum()">
<table border="0" align="center" >
<tr>
<td>第<%=pages%>页 共<%=totalpages%>页 <a href="index.jsp?pages=1">首页</a></td>
<td><a href="index.jsp?pages=<%=(pages<1)?pages:(pages-1) %>"> 上一页</a></td>
<td><a href="index.jsp?pages=<%=(pages>=totalpages)?totalpages:(pages+1)%>"> 下一页</a></td>
<td><a href="index.jsp?pages=<%=totalpages%>">最后一页</a></td>
<td>转到第:<input type="text" name="page" size="8">页<input type="submit" value="GO" name="cndok"></td>
</tr>
</table>
</form>
附:常见数据库分页查询语句
1.oracle数据库分页
select * from (select a.*,rownum rc from 表名 where rownum<=endrow) a where a.rc>=startrow
2.DB2数据库分页
Select * from (select rownumber() over() as rc,a.* from (select * from 表名 order by列名) as a) where rc between startrow and endrow
3.SQL Server 2000数据库分页
Select top pagesize * from 表名 where 列名 not in(select top pagesize*page 列名 from 表名 order by列名) order by列名
4.SQL Server 2005数据库分页
Select * from (select 列名,row_number() over(order by 列名1) as 别名from 表名) as t where t.列名1>=startrow and t.列名1<=endrow
5.MySQL数据库分页
Select * from 表名 limit startrow,pagesize
(Pagesize为每页显示的记录条数)
6.PostgreSQL数据库分页
Select * from 表名 limit pagesize,offset startrow
(Pagesize为每页显示的记录条数)
转载请注明原文地址:http://www.cnblogs.com/ygj0930/p/6134851.html
项目开发过程中,分页是少不了的,之前封装了一个分页组件,样式是基于bootstrap的样式,当然也可以自己来修改;
别的不说,上图上代码;
bootstrap样式分页
以下是相关代码:
/***=======================分页样式==================================***/
/*分页样式*/
.page{
display:inline-block;
width:100%;
text-align:center;
height:35px;
line-height:35px;
background-color:none;
}
.page .pagination{
margin:0px !important;
}
.page .pagination li a{
/*修改按钮样式*/
border:none !important;
background-color:transparent; !important;
color:#555;
cursor:pointer;
}
.page .pagination li a:hover,.page .pagination li a:focus,.page .pagination li a:active{
background-color:#ccc;
}
.page .pagination li.active a,.page .pagination li.active a:hover,.page .pagination li a:active,.page .pagination li a:focus{
color:#0099ff;
cursor:default;
background-color:none;
}
.pageinfo{
display:none !important;
}
/*隐藏分页信息*/
.clickmore{ cursor:pointer; }
.pagination>.action>a:hover,.pagination>.action>a:focus{ color:#0099ff !important; cursor:default; }
/****======================分页样式结束============================***/
上面是自己写的分页样式,可自行修改之,下面是分页组件代码:
/**
* bootstrap 对应的独立分析组件
* @demo
* pagination.init({
* selector : '.page', //选择器,作为渲染目标,默认为 '.page.pagination',非必须
* count : 120, //为总记录数,必须
* isTransform : false,//是否转换为符合后台需要的参数begin /end
* page : 1, //为当前页码,非必须
* pagesize : 10, //为每页条数,默认10,非必须
* increment : 10, //为页面存在的分页增量,比如只显示5个页码,非必须
* pageArray : [], //可以进行生成下拉框,比如 10,20,50 ,选择不同的页码进行分页,非必须
* previousTitle : '点击查看',//为上一页的title显示,未实现;
* callback : function(pageObject){//为分页点击回调函数,必须
* console.log(pageObject);//pageObject={page : 1,pagesize:10};回调函数返回值,包括下一个页码和每页条数
* }
* });
* @since 2016年2月15日 15:18:36
* @author lixun
* @version 1.0
* @edited by lixun ,增加多实例;一个页面多个分页 ;
* 处理思路:
* 1\. 对应的每个selector有一个pagination,然后在调用的时候根据selector进行查找
* 2\. 处理的内容:1)分页加载;2)事件绑定 3)回调函数
* 3\. 处理原则:平滑处理,原有的可继续使用;
*/
var pagination={
_defaultSelector : '.page .pagination', //默认选择器
_defaultPagesize : 20, //默认分页条数
_defaultIncrement : 10, //默认分的页码数
_defaultPageArray : [10,20,50,100], //默认的条码下拉框
_map : { //用户处理多实例增加的容器,不可覆盖
//selector : {私有属性}
//".page .column" : {}
},
//通用属性
lastSelector : '',//上一个选择器,用于开发者不传递参数的时候,去查找上一个选择器用的。
previousTitle : '上一页',
nextTitle : '下一页',
previousContent : '上一页',
nextContent : '下一页',
//获得分页实例
_getPagination : function(selector){
if(null !=selector && selector !='' && $(selector).length > 0){
return pagination._map[selector];
}else{
console.error('selector 传参错误或$('+selector+')不存在!');
}
return null;
},
//获得返回的字符串
pageArrayStr : function(selector,ps){
var pa=pagination._map[selector].pageArray;
if(null !=pa && pa.length > 0){
var concatStr='<select onchange="pagination.changePagesize(\''+(selector)+'\',event)" style="height:20px;line-height:20px;padding:0px;margin-top:-2px;">';
var i=0,max=pa.length;
for(;i<max;i++){
var v=pa[i];
concatStr +='<option value="'+v+'" '+(v==ps ? 'selected="true"' : '')+'>'+v+'</option>';
}
concatStr +='</select>';
return concatStr;
}
return "";
},
//绑定事件
bindEvent : function(selector){
if(selector && selector !=''){
var _tempPaginationInstance=pagination._map[selector] || {};
var _bindE=_tempPaginationInstance.bindE==true ? true : false;
if(_bindE==false){
_tempPaginationInstance.bindE=true;
pagination._map[selector]=_tempPaginationInstance;
//跳转页面
$(selector).delegate('li.unselect','click',pagination.clickpage);
//绑定上一页事件
$(selector).delegate('li.pageup','click',pagination.pageup);
//绑定下一页事件
$(selector).delegate('li.pagedown','click',pagination.pagedown);
//绑定前面页面事件
$(selector).delegate('a.previous','click',pagination.previouspage);
//绑定后面页面事件
$(selector).delegate('a.next','click',pagination.nextpage);
}
}
},
//分页初始化
init : function(params){
//处理传参数据
params=params || {};
params.count=params.count || 0;
params.pagesize=params.pagesize || pagination._defaultPagesize;
var paramSelector=pagination._defaultSelector;
if(params.selector){
paramSelector=params.selector;
}
//获得选择器后,进行实例处理
var paginationInstance=pagination._getPagination(paramSelector);
//传参获取最新配置
var tempPaginationInstance={
selector : paramSelector,
page : params.page ? params.page : (paginationInstance && paginationInstance.action==true ? (paginationInstance.page ? paginationInstance.page : 1) : 1),
count : params.count || 0,
action : false,
bindE : false,//是否绑定事件
pagesize : params.pagesize,
callback : params.callback || $.noop,
pagenumber : (parseInt((params.count || 0)/(params.pagesize||pagination._defaultPagesize),10)+((params.count||0)%(params.pagesize||pagination._defaultPagesize)==0 ? 0 : 1)),//根据总数和一页条数获得页码数量
increment : params.increment || pagination._defaultIncrement,
pageArray : params.pageArray || pagination._defaultPageArray
};
if(paginationInstance && undefined !=paginationInstance){
//存在实例,进行更新。
tempPaginationInstance.bindE=true;//如果存在的话,肯定绑定了
pagination._map[paramSelector]=$.extend(paginationInstance,tempPaginationInstance);
}else{
pagination._map[paramSelector]=tempPaginationInstance;//重新赋值
pagination.bindEvent(paramSelector);//绑定事件
}
pagination.loadPage(paramSelector);
pagination.lastSelector=paramSelector;
},
//点击页面数直接跳转
clickpage : function(){
var $a=$(this).find('a');
var selector=$a.attr('selector');
var gonumber=parseInt($a.html(),10);
$(selector+' li.active').addClass('unselect').removeClass('active');
$(this).addClass('active').removeClass('unselect');
pagination.gopage(selector,gonumber);
},
//向上翻页
pageup : function(){
var $a=$(this).find('a');
var selector=$a.attr('selector');
var _tempInstance=pagination._map[selector];
if(_tempInstance){
//得到当前页面,然后翻页,如果在边界,那么就要进行触发一次翻页事件
var $actel=$(selector+' li.active a');
var nownumber=parseInt($actel.html(),10);
if(nownumber==1){
return false;
}else{
pagination.gopage(selector,nownumber-1);
}
}
},
//向下翻页
pagedown : function(){
var $a=$(this).find('a');
var selector=$a.attr('selector');
var _tempInstance=pagination._map[selector];
if(_tempInstance){
var pagenumber=_tempInstance.pagenumber;
//获得该实例的分页码数
var $actel=$(selector+' li.active a');
var nownumber=parseInt($actel.html(),10);
if(nownumber==pagenumber){
return false;
}else{
pagination.gopage(selector,nownumber+1);
}
}
},
//前面页面
previouspage : function(){
var selector=$(this).attr('selector');
var _tempInstance=pagination._map[selector];
if(_tempInstance){
var increment=_tempInstance.increment,
page=_tempInstance.page;
//判断当前是第几个,比如16,那么就以10的倍数向前翻页
var $nowobj=$(selector+' a.previous').parent();
var nextnumber=parseInt($nowobj.next().children().html(),10);
var end=(nextnumber-1)%increment > 0 ? parseInt((nextnumber/increment),10)*increment : parseInt((nextnumber/increment-1),10)*increment;
pagination.gopage(selector, end+1);
}
},
//后面页面
nextpage : function(){
//判断当前点击的哪些,比如:现在是5,点击生成6...
var selector=$(this).attr('selector');
var _tempInstance=pagination._map[selector];
if(_tempInstance){
var increment=_tempInstance.increment;
var $nowobj=$(selector+' a.next').parent();
var prenumber=parseInt($nowobj.prev().children().html(),10);
if(parseInt(prenumber/5,10)==1){//说明在第一页,要从5加载5个,直到结束
pagination.addPage(selector,$nowobj,5);
}else{
//第二次 增加页面数量了,应该是从10开始了...
pagination.addPage(selector,$nowobj,increment);
}
}
},
addPage : function(selector,domobj,size){
var _tempInstance=pagination._map[selector];
if(_tempInstance){
var pagenumber=_tempInstance.pagenumber,
increment=_tempInstance.increment;
var start=parseInt(domobj.prev().children().html(),10);
pagination.gopage(selector, start+1);
}
},
loadPage : function(selector){
//根据selector获得count,pagesize,page
var _tempInstance=pagination._map[selector];
if(!_tempInstance){
console.log('error : _tempInstance is null now ,check pagination params please!');
return null;
}
var count=_tempInstance.count,
pagesize=_tempInstance.pagesize,
page=_tempInstance.page,
increment=_tempInstance.increment,
pageArrayStr=pagination.pageArrayStr(selector,pagesize),
pagenumber=_tempInstance.pagenumber;
var $page=$(selector);
//清空内容
$page.html('');
var pageno=pagenumber;
page=page > pageno ? 1 : page; //如果当前页码树大于总页码数则置为1,否则为当前页码数;
//如果页数超过10,则增...,以5个数字递增,
//显示到page页面的下一个5的倍数上。
var endpage=(parseInt(page/increment,10))*increment > pageno ? pageno : (parseInt(page/increment,10)+(page%increment==0 ? 0 : 1))*increment;
if(pageno<=increment){
endpage=pageno;
}
var pageHtml='';
if(pageArrayStr==''){
}else if(pagination._map[selector].pageArray.length==1){
pageHtml='<li class="pageinfo">共'+count+'条 </li>';
}else{
pageHtml='<li class="pageinfo">共'+count+'条 , 每页'+pageArrayStr+'条</li>';
}
$page.append(pageHtml);
$page.append('<li class="prev pageup '+(page==1 ? 'disabled' : '')+'"><a title="'+pagination.previousTitle+'" href="javascript:;" selector="'+(selector)+'">'+pagination.previousContent+'</a></li>');
//判断第几页
var start=0;
if(page > increment && page <=pageno){
$page.append('<li><a class="previous" href="javascript:;" selector="'+(selector)+'">...</a></li>');
//给一个自定义增长数量,比如5个,每次增长五个,当前页面6页面,增长5个为10个,start page为 6
start=parseInt((page%increment==0 ? (page-1) : page)/increment,10)*increment;
endpage=(start+increment ) > pageno ? pageno : (start+increment);//如果开始页面加上增加页面大于最大页码数,则等于最大页码数
if(endpage-page <increment){
start=endpage-increment;
}
}
for(var i=start;i<(endpage==0?1:endpage);i++){
var listr='<li class="unselect"><a href="javascript:;" selector="'+(selector)+'">'+(i+1)+'</a></li>';
//在第page页面增加样式
if((page-1)==i){
listr='<li class="active"><a selector="'+(selector)+'">'+(i+1)+'</a></li>';
}
$page.append(listr);
}
if(pageno > 5 && endpage !=pageno){
$page.append('<li><a class="next" href="javascript:;" selector="'+(selector)+'">...</a></li>');
}
$page.append('<li class="next pagedown '+(page==pageno ? 'disabled' : '')+'"><a title="'+pagination.nextTitle+'" href="javascript:;" selector="'+(selector)+'">'+pagination.nextContent+'</a></li>');
},
//跳转页面
gopage : function(selector,page){
var _tempInstance=pagination._map[selector];
if(_tempInstance){
_tempInstance.page=page;
_tempInstance.action=true;
_callback=_tempInstance.callback;
_pagesize=_tempInstance.pagesize;
pagination._map[selector]=_tempInstance;
_callback(pagination.transform({
page : page,
rows : _pagesize
}));
}
},
/*返回现在的页面*/
getNowPage : function(selector){
selector=selector || (pagination.lastSelector || pagination._defaultSelector);//获取上一个选择器
var _tempInstance=pagination._map[selector];
if(_tempInstance){
_tempInstance.action=true;
var _page=_tempInstance.page,
_pagesize=_tempInstance.pagesize;
pagination._map[selector]=_tempInstance;
return pagination.transform({
page : _page,
rows : _pagesize
});
}
return null;
},
transform : function(paginationParams){
if(pagination.isTransform && pagination.isTransform==true){
var p=paginationParams.page || 1;
var rows=paginationParams.pagesize || 10;
return {
begin : (p-1)*rows+1,
end : p*rows
};
}
return paginationParams;
},
//返回分页参数,以供列表页面加载数据使用
getParams :function(selector){
selector=selector || (pagination.lastSelector || pagination._defaultSelector);//获取上一个选择器
var _tempInstance=pagination._map[selector];
if(_tempInstance){
var _pagesize=_tempInstance.pagesize;
return pagination.transform({
//第几页,一页有多少条记录
page:1,
rows : _pagesize
});
}
return null;
},
changePagesize : function(selector,ev){
var t=ev.currentTarget || ev.target || ev.srcElement,
$t=$(t),
v=$t.find('option:selected').val();
// selector=$t.attr('selector');
var _tempInstance=pagination._map[selector];
if(_tempInstance){
_tempInstance.pagesize=v;
var _callback=_tempInstance.callback;
pagination._map[selector]=_tempInstance;
//重新调用callback方法
_callback(pagination.transform({
page : 1,
rows : v
}));
}
}
};
文章首发于 BUG集散地 ,https://chrunlee.cn/article/pagination-web-javascript.html
*请认真填写需求信息,我们会在24小时内与您取得联系。