无刷新分页技术
技术点:JQuery+JSON
步骤1:贴下面的JS插件
split_util.js
var jsCommonCp=1 ; //默认显示第一页
var jsCommonLs=10 ; //默认显示10条数据
var jsCommonPageSize ; //总页数,将其定义为全局变量
var jsCommonCol="" ; //列名称
var jsCommonKw="" ; //关键词
function createSplitBar(data){ //创建分页条
// console.log("allRecords:"+allRecords) ;
calcPageSize(data.allRecords) ; //分页开始之后首先要计算总页数
clearBar() ; //清空已有的分页数据条,避免重复生成
//创建分页工具条
// console.log("jsCommonCp:"+jsCommonCp) ;
previousPageBar() ;
addBar(1) ; //第一页应该一直出现
var seed=3 ; //定义种子数
if(jsCommonCp>seed*2){ //超过预期的内容才会出现
addDetailsPageBar() ; //增加省略页面
var startPage=jsCommonCp-seed ; //开始页
for(var x=startPage;x<=jsCommonCp+seed;x++){
if(x<jsCommonPageSize){
addBar(x) ;
}
}
if(jsCommonCp+seed*2<jsCommonPageSize){ //后面还有很多页
addDetailsPageBar() ; //增加省略页面
}
}else{ //现在的页数还小于种子数
for(var x=2;x<jsCommonCp+seed;x++){
addBar(x) ;
}
if(jsCommonCp+seed<jsCommonPageSize){ //后面还有很多页
addDetailsPageBar() ; //增加省略页面
}
}
addBar(jsCommonPageSize) ; //尾页应该一直出现
nextPageBar() ;
} ;
function addBar(index){ //定义一个函数专门负责追加每一个li元素实现分页的控制颗粒
var liObj=$("<li></li>") ; //先创建元素在配置,因为后面牵扯到事件问题
var aObj=$("<a style=\"cursor:pointer\">"+index+"</a>") ;
if(jsCommonCp == index){ //现在为当前所在页
aObj.addClass("active") ; //表示当前页为可用页
}else{
aObj.on("click",function(){
jsCommonCp=index ; //改变当前页为可用页
loadData() ; //重新加载新的数据
}) ;
}
liObj.append(aObj) ;
$("#pageControl").append(liObj) ; //追加到分页控制条
} ;
//如果要想进行分页,那么必须知道到底有多少页,那么这个总页数是通过计算得来的
function calcPageSize(allRecords){ //计算总页数
if(allRecords==0){
jsCommonPageSize=1 ; //保持1页
}else{
//此时计算总页数时一定会存在小数点问题,将其用parseInt()函数解决掉
jsCommonPageSize=parseInt((allRecords+jsCommonLs-1)/jsCommonLs);
}
} ;
function clearBar(){
$("#splitBarDiv").empty() ; //清空分页条所有的内容
$("#splitBarDiv").append("<ul id=\"pageControl\" class=\"pagination\"></ul>") ; //追加一个ul
} ;
function previousPageBar(){
var liObj=$("<li></li>") ; //先创建元素在配置,因为后面牵扯到事件问题
var aObj=$("<a style=\"cursor:pointer\">上一页</a>") ;
if(jsCommonCp == 1){ //现在为第一页
aObj.addClass("disabled") ; //如果为第一页,则上一页不可用
}else{
aObj.on("click",function(){
if(jsCommonCp>1){
jsCommonCp-- ; //改变当前页为上一页
loadData() ; //重新加载新的数据
}
}) ;
}
liObj.append(aObj) ;
$("#pageControl").append(liObj) ; //追加到分页控制条
} ;
function nextPageBar(){
var liObj=$("<li></li>") ; //先创建元素在配置,因为后面牵扯到事件问题
var aObj=$("<a style=\"cursor:pointer\">下一页</a>") ;
if(jsCommonCp == jsCommonPageSize){ //现在为尾页
aObj.addClass("disabled") ; //如果为尾页,则下一页不可用
}else{
aObj.on("click",function(){
if(jsCommonCp < jsCommonPageSize){
jsCommonCp++ ; //改变当前页为下一页
loadData() ; //重新加载新的数据
}
}) ;
}
liObj.append(aObj) ;
$("#pageControl").append(liObj) ; //追加到分页控制条
} ;
function addDetailsPageBar(){ //增加省略页
$("#pageControl").append("<li><span>...</span></li>");
} ;
split_search.js
//<div id="searchDiv"></div>
function createSearchBar(data){ //生成检索框
jsCommonCol = data.col ; //当前使用的模糊查询列
jsCommonKw=data.kw ; //当前使用的默认关键字
clearSearchBar() ; //清空原有的搜索框
addSelectColumn(data.columnData) ; //创建下拉列表框
addSearchText(jsCommonKw,data.allRecords) ; //创建搜索框
} ;
function clearSearchBar(){
$("#searchDiv").empty() ;
} ;
function addSearchText(kw,allRecords){
$("#searchDiv").append("<input type=\"text\" name=\"kw\" id=\"kw\" value=\""+kw+"\">") ;
var butObj=$("<input type=\"button\" value=\"检索\">") ; //检索按钮
butObj.on("click",function(){
jsCommonCol=$("#col").val() ; //重新读取下拉列表的值
jsCommonKw=$("#kw").val() ; //重新读取关键词
loadData() ; //重新加载数据
}) ;
$("#searchDiv").append(butObj) ;
$("#searchDiv").append("<div>本次查询一共返回了"+allRecords+"条记录</div>") ;
} ;
function addSelectColumn(columnData){
var selectObj=$("<select id=\"col\"></select>");
var result=columnData.split("|") ; //拆分字符串
for(var x=0;x < result.length;x++){
var temp=result[x].split(":") ; //保存每一个字段
if(jsCommonCol==temp[1]){
selectObj.append("<option value=\""+temp[1]+"+\" selected>"+temp[0]+"</option>") ; //选中
}else{
selectObj.append("<option value=\""+temp[1]+"\" >"+temp[0]+"</option>") ;
}
}
$("#searchDiv").append(selectObj) ;
} ;
以上两个插件不用改变,直接贴代码就行
步骤二:编写HTML/JSP页面
dept_list.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta http-equiv="x-ua-compatible" content="ie=edge">
<title>无刷新分页技术</title>
<script type="text/javascript" src="jquery/jquery-1.11.2.min.js"></script>
<script type="text/javascript" src="jquery/bootstrap.min.js"></script>
<script type="text/javascript" src="js/split_util.js"></script>
<script type="text/javascript" src="js/split_search.js"></script>
<script type="text/javascript" src="js/dept_list.js"></script>
<link href="css/bootstrap.min.css" rel="stylesheet" type="text/css" />
</head>
<body>
<div id="searchDiv"></div>
<div id="deptDiv">
<table border="1" id="deptTab">
<tr>
<td>部门编号</td>
<td>部门名称</td>
</tr>
</table>
</div>
<div id="splitBarDiv"></div>
</body>
</html>
dept_list.js
$(function(){ //只要是无刷新分页,就要进行Ajax动态设置
loadData() ; //只要调用这个函数就可以实现表格数据填充以及分页的自动生成
}) ;
function loadData(){ //负责数据的加载
//此处既然是无刷新分页,那么就要进行异步数据加载
$.post("PageServlet",{
"cp" : jsCommonCp ,
"ls" : jsCommonLs ,
"col" : jsCommonCol ,
"kw" : jsCommonKw
} ,function(json){
createSplitBar(json); //有总记录数才能驱动分页组件
createSearchBar(json) ; //生成检索框
//随后生成分页的数据,会有所不同
clearTable() ; //清空表格行
for(var x=0;x<json.allDepts.length;x++){
var deptno=json.allDepts[x].deptno ;
var dname=json.allDepts[x].dname ;
addTableRow(deptno,dname) ; //增加行
}
},"json");
} ;
function addTableRow(deptno,dname){
$("#deptTab").append("<tr><td>"+deptno+"</td><td>"+dname+"</td></tr>");
} ;
function clearTable(){ //清空表格行
$("#deptTab tr:gt(0)").remove(); ;
} ;
总结:
以上的两个文件必须做改写:Ajax的URL、表格的格式、生成row的函数;
其实无刷新分页节省了和后台的交互
步骤三:控制层代码
PageServlet.java
package cn.zzu.wcj.servlet;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
@WebServlet(urlPatterns="/PageServlet")
public class PageServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
@Override
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//分页操作的几个核心参数:cp,ls,col,kw
request.setCharacterEncoding("UTF-8") ;
response.setCharacterEncoding("UTF-8") ;
response.setContentType("text/html");
int currentPage=1 ;
int lineSize=5 ;
String column=null ;
String keyWord=null ;
try{
currentPage=Integer.parseInt(request.getParameter("cp")) ;
}catch(Exception e){}
try{
lineSize=Integer.parseInt(request.getParameter("ls")) ;
}catch(Exception e){}
column=request.getParameter("col") ;
keyWord=request.getParameter("kw") ;
if(column==null || "".equals(column)){
column="dname" ;
}
if(keyWord==null){
keyWord="" ;
}
String columnData="部门编号:deptno|部门名称:dname|部门位置:loc" ;
System.out.println("[分页参数]cp="+currentPage+",ls="+lineSize+",col="+column+",kw="+keyWord);
JSONObject all=new JSONObject() ;
all.put("allRecords", 4800) ;
all.put("columnData", columnData) ; //作为下拉列表内容存在
all.put("col", column) ; //回传列
all.put("kw", keyWord) ; //回传关键词
JSONArray array=new JSONArray() ;
//模拟JDBC
for(int x=currentPage*lineSize;x<currentPage*lineSize+10;x++){
JSONObject obj=new JSONObject() ;
obj.put("deptno", x) ;
obj.put("dname", "ZZU-"+x) ;
array.add(obj) ;
}
all.put("allDepts", array) ;
response.getWriter().print(all);
}
@Override
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
this.doGet(request, response);
}
}
总结:
这里最需要注意几个参数的回传:allRecords、columnData、col、kw(columnData和数据库字段和中文名要一一对应,如”部门编号:deptno|部门名称:dname|部门位置:loc”)、allDepts(换成你想要传回的数据) , 接收:cp、ls、col、kw;
结合SpringMVC或Struts2把以上的控制层改写进去,就可以完成无刷新分页,我之前的写的分页插件没这个好用,大家可以结合Bootstrap让这个分页插件更炫酷