分页开发准备
-
本次实现一个无刷新的分页操作,同时考虑到代码重问题,需要将这些代码做成一个组件,需要清楚的是,如果使用无刷新的分页处理,实际上就是使用的DOM处理,如果使用DOM处理使用jQuery是最容易的.
-
模拟一些真是的数据库环境,对于实际的分页而言,有以下几个内容需要服务器端返回的:
- 所有的数据(allDepts):假设本次实现的是一个部门数据的列表
- 所有的数据量(allRecorders):实际中的数据量需要通过统计函数计算而来,本次使用固定的内容,对于于分业而言需要如下参数:cp:当前所在页,ls-每夜现实的数据行,模糊查询列cal,模糊查询关键字:kw
- 本次使用JSON作为数据的返回操作
-
建立一个PageModule项目()动态web项目
-
建立一个PageServlet,这个Servlet只是负责信息的显示()本次不链接数据库
package mao.shu.servlet;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
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 java.io.IOException;
import java.util.Enumeration;
@WebServlet("/PageServlet")
public class PageServlet extends HttpServlet {
@Override
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("UTF-8");
response.setCharacterEncoding("UTF-8");
response.setContextType("application/json","UTF-8");
//定义分页的默认数据
int currentPage = 1;//默认当前所在页
int linesize = 10;//默认每页现实的数据个数
String keyword = "";//默认没有模糊查询关键字
String column = "dname";
//从请求路径中接收分页数据
try{
currentPage = Integer.parseInt(request.getParameter("cp"));
}catch (Exception e){e.printStackTrace();}
try{
linesize = Integer.parseInt(request.getParameter("ls"));
}catch (Exception e){e.printStackTrace();}
if(request.getParameter("ky")!=null){
keyword = request.getParameter("ky");
}
if(request.getParameter("col")!=null){
column = request.getParameter("col");
}
//模拟一些数据,该数据使用JSON格式数据包裹
JSONObject jsonObject = new JSONObject();
jsonObject.put("allRecorders",80);//模拟总数据为80条
JSONArray allDepts = new JSONArray();//保存数组内容
for (int i = (currentPage-1)*linesize+1; i <= currentPage*linesize ; i++) {
if (i >= 80){
break;
}
JSONObject temp = new JSONObject();
temp.put("deptno",i);
temp.put("dname","dname-"+i);
temp.put("loc","loc-"+i);
allDepts.add(temp);
}
jsonObject.put("allDepts",allDepts);
//将所有数据打印到页面中
response.getWriter().print(jsonObject);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doGet(request, response);
}
public void printParam(HttpServletRequest request){
Enumeration<String> name = request.getParameterNames();
while(name.hasMoreElements()){
String temp = name.nextElement();
System.out.println("[参数名称] = "+temp+":"+request.getParameter(temp));
}
}
}
- 此时Servlet已经可以正常运行了
- 创建前端页面
<html>
<head>
<title>部门信息</title>
<meta charset="UTF-8">
<script type="text/javascript" src="js/jquery.min.js"></script>
<script type="text/javascript" src="js/dept_list.js"></script>
<script type="text/javascript" src="js/util/split_plugin_search.js"></script>
<script type="text/javascript" src="js/util/split_plugin_bar.js"></script>
</head>
<body>
<!--放置分页插件的层-->
<div id="splitPluginSearchDiv"></div>
<!--显示数据层-->
<div id="deptTabletDiv">
<table id="deptTable" border="1" width="100%">
<tr id="dept-title">
<td id="deptno-title">部门编号</td>
<td id="dname-title">部门名称</td>
<td id="loc-title">部门位置</td>
</tr>
</table>
</div>
<!--放置分页插件的div层-->
<div id="splitPluginBanderDiv"></div>
</body>
</html>
-
为了能够将分页功能做成能够可重用的代码,应该将分页的搜索功能操作写在split_plugin_search.js文件中,将分页下的切换页面功能写在split_plugin_bar.js文件中.
-
而每个数据分页的情况都不一样,这些不相同的部分因该有使用分页者自己完成,现在规定使用分页组件者应该将自定义的操作写在loadData()函数中完成
-
dept_list.js文件
$(function(){
loadData();
});
//规定使用分页组件必须编写koadData()函数
function loadData(){
//向Servlet中发送请求,返回的一定是json格式数据
$.post("PageServlet",{"cp":jsParamCP,"ls":jsParamLS,"kw":jsParamKW,"col":jsParamCOL},
function(data){
//再追加数据前,先清空原表格数据
clearTable();
//返回的数据中包含有一组部门信息,使用的是json数组包装起来的
for(var x=0;x <data.allDepts.length;x++){
//取出每个部门的信息,交给addRow()函数处理,为表格添加数据
addRow(data.allDepts[x].deptno,data.allDepts[x].dname,data.allDepts[x].loc);
}
},"json")
}
//清空表格中的数据
function clearTable(){
//保留第一个表头
$("#deptTable tr:gt(0)").empty();
}
//添加表格行数据
function addRow(deptno,dname,loc){
$("#deptTable").append("<tr>" +"<td>"+deptno+"</td>" +"<td>"+dname+"</td>"+"<td>"+loc+"</td>"+ "</tr>")
}
- 分页所需的数据应该交由组件控制,所以将分页所需的数据定义在split_plugin_bar.js中
//由split_plugin_bar.js来控制分页所需的数据
var jsParamCP = 1;
var jsParamLS = 10;
var jsParamKW = "";
var jsParamCOL = "dname";
基础分页
- 现在整个程序的实现架构已经出现了,那么随后要处理的问题就是如何生成分页条,如果要想生成分也条可以借助于一些样式.
- 将分页的样式拷贝到css目录中
- 在以诶暗中进行改样式的导入
- 一定要充分考虑到代码的宠用型设计,所以这个时候,用户可以看到的操作应该越少越好
- 在solit_liugin_bar.js中定义一个函数,该函数中完成分页按钮的所有操作
- 在split_plutin_bar.js文件中秩序进行分页的具体实现
- 如果要进行分页处理,那么首先一定要知道总页数,但是总页数都是需要计算的来,并且所有接收到的数据都是字符串类型,为了达到可重用的调用,在split_plulin_bar.js文件中国新建立一个函数,calaAllpageSize()
- 修改split_plugin_bar.js文件
//由split_plugin_bar.js来控制分页所需的数据
var jsParamCP = 1;
var jsParamLS = 10;
var jsParamKW = "";
var jsParamCOL = "dname";
var jsParamAllPageSize = 1;//保存分页总页数
function createPageNumber(data){
calcAllPageSize(data.allRecorders);
}
function calcAllPageSize(allRecorders){
if (allRecorders == 0){
jsParamAllPageSize == 1;
}else{
jsParamAllPageSize = parseInt((allRecorders+jsParamLS-1)/jsParamLS);
console.log(jsParamAllPageSize);
}
}
- 分页按钮的样式使用的是bootstrap中的按钮样式,在页面中"splitPluginBanderDiv"层生成页码按钮.
- 但是为了方便每次添加页面,定义一个clearBander()函数,该函数负责清空原始的页码按钮元素.而后生成新的存放页码按钮的"ul"元素
function clearBaner(){
//清空原始的数据
$("#splitPluginBanderDiv").empty();
//生成新的分页按钮ul
$("#splitPluginBanderDiv").append("<ul class='pagination'></ul>")
}
- 那么每次在生成新的分也条之前需要将原始的分页条清除掉,
function createPageNumber(data){//创建分页按钮的函数
clearBaner();//清空分页按钮
calcAllPageSize(data.allRecorders);
}
- 考虑到有可能进行分页页码的动态生成处理,所以可以定义一个函数.addBar(),该函数
function addBar(index){//进行页码按钮的追加,index为页码内容
var liobj = $("<li></li>");//每个页码按钮都是用li元素表示
if(jsParamCP == index){//如果当前所在页于要生成的页码正好一样
var spanObj = $("<a>"+index+"</a>");
liobj.attr("class","active");
liobj.append(spanObj);
}else{
var aObj = $("<a>"+index+"</a>");//如果生要生成的页码并不是当前所在页
aObj.on("click",function(){
//改变当前所在页
jsParamCP = index;
//重新加载页面
loadData();
});
liobj.append(aObj);
}
$("#PageNumUl").append(liobj);
}
- 而后在createPageNumber()函数中,通过循环的方式,生成页码
function createPageNumber(data){//创建分页按钮的函数
clearBaner();//清空分页按钮
calcAllPageSize(data.allRecorders);
for(var x =1; x <=jsParamAllPageSize;x++){//根据总页数生成页码
addBar(x);
}
}
- 在dept_list.js中,当用户使用loadData()函数的时候,只需要调用createPageNumber()这个函数完成分页页码的生成即可
function loadData(){
//向Servlet中发送请求,返回的一定是json格式数据
$.post("PageServlet",{"cp":jsParamCP,"ls":jsParamLS,"kw":jsParamKW,"col":jsParamCOL},
function(data){
//创建分页页码
createPageNumber(data);
//再追加数据前,先清空原表格数据
clearTable();
//返回的数据中包含有一组部门信息,使用的是json数组包装起来的
for(var x=0;x <data.allDepts.length;x++){
//取出每个部门的信息,交给addRow()函数处理,为表格添加数据
addRow(data.allDepts[x].deptno,data.allDepts[x].dname,data.allDepts[x].loc);
}
},"json")
}
- 基础分页效果
分页控制加强
- 大部分的分页代码里面一定会有上一页以及下一页的操作处理,所以可以为此增加这样的功能
- 定义一个新的函数,用户生成上一页
//创建上一页
function createLastPage(){
var liobj = $("<li></li>");
//如果当前所在页为1,表示已经到顶不了,不能再点击上一页了
if(jsParamCP==1){
liobj.attr("class","disabled");
liobj.append("<span>上一页</span>");
}else{
var aobj = $("<a style='cursor:pointer'>上一页</a>");
aobj.on("click",function(){
jsParamCP--;
loadData();
});
liobj.append(aobj);
}
$("#PageNumUl").append(liobj);
}
- 定义一个函数为上一页的功能
//创建下一页
function createNextPage(){
var liobj = $("<li></li>");
//如果当前所在页为总页数,表示已经到底了
if(jsParamCP==jsParamAllPageSize){
liobj.attr("class","disabled");
liobj.append("<span>下一页</span>");
}else{
var aobj = $("<a style='cursor:pointer'>下一页</a>");
aobj.on("click",function(){
jsParamCP++;
loadData();
});
liobj.append(aobj);
}
$("#PageNumUl").append(liobj);
}
- 对于这两个操作函数,应该在整个分页条前后执行
function createPageNumber(data){//创建分页按钮的函数
clearBaner();//清空分页按钮
calcAllPageSize(data.allRecorders);
createLastPage();//创建上一页按钮
for(var x =1; x <=jsParamAllPageSize;x++){//根据总页数生成页码
addBar(x);
}
createNextPage();//创建下一页按钮
}
-
在整个代码的处理过程之中,必须清楚一个问题,如果页码如果很多,那么就必须生成省略号,那么这个时候对于addBar()就不能够直接通过循环生成
-
但是有几样按钮是可以单独存在的
- 上一页
- 下一页
- 首页(第一页)
- 尾页(最后一页,使用jsParamAllPageSize变量表示)
-
定义一个专门增加省略点的函数
//创建省略号
function createEllipses(){
var elliObj = $("<li><span>...</span></span></li>");
$("#PageNumUl").append(elliObj);
}
-
在createPageNumber()函数中,定义一个种子数,根据这个种子树判断是否使用省略号代替.
- 具体判断是这样的,定义一个种子数,例如:3,使用当前页数和种子树比较,
- 如果当前页数小于种子树的两倍,则认为页面可以正常显示,并且每次切换页数都显示当前页数后两位.如果当前页数加上两倍的种子数还是小于总页数,则后面使用省略号表示
- 如果当前页数大于种子数的两倍,则认为页数过多,前面部分使用省略号表示,中间显示当前所在页的前三个和后三个按钮,如果当前所在页数加上两倍的种子数,还是小于总页数,则后半部分使用省略号表示.
-
修改createPageNumber()函数
{//创建分页按钮的函数
clearBaner();//清空分页按钮
calcAllPageSize(data.allRecorders);
createLastPage();//创建上一页按钮
addBar(1);//第一页
var seed = 3;//判断总页数是否过大的种子数
if(jsParamCP < seed*2){//此时页数并不多
for(var x=2;x<jsParamCP+seed;x++){
if(x<jsParamAllPageSize) {
addBar(x);
}
}
if(jsParamCP+seed < jsParamAllPageSize){//如果后面依然后许多页数
createEllipses();//使用省略号代替
}
}else{//此时页数较多
//前面部分使用省略号表示
createEllipses();
//显示出当前前三个和,当前后三个按钮
var startIndex = jsParamCP-seed;
for (var i = startIndex; i <=jsParamCP+3; i++) {
if(i < jsParamAllPageSize) {//去掉大于总页数的按钮
addBar(i);
}
}
if(jsParamCP+seed < jsParamAllPageSize){//如果后面依然后许多页数
createEllipses();//使用省略号代替
}
}
addBar(jsParamAllPageSize);
createNextPage();//下一页
}
- 此时的页面效果
模糊索引
- 在实际开发里面,模糊查询的操作一定是用户自己操作处理的,但是在模糊查询是需要求改PageServlet.java文件
- 在PageServlet里面,返回模糊查询的选择列,依然按照"标签名称:列名称"格式返回
- 每次请求时可能会发送一个模糊查询列和一个模糊查询关键字,在回应输出时应该将这两个值也带上
- 修改PageServlet.java程序类
//模拟一些数据,该数据使用JSON格式数据包裹
JSONObject jsonObject = new JSONObject();
jsonObject.put("columnData","deptno:部门编号|dname:部门名称");
jsonObject.put("keyword",keyword);
jsonObject.put("column",column);
- 对于模糊查询而言,那么用户可以处理的操作很简单,也应该像分页码一样给一个函数
- 在split_plugin_search.js文件中定义一个createSearch()函数
//添加搜索框组件
function createSearch(data){
jsParamKW = data.keyword;
jsParamCOL = data.column;
$("#splitPluginSearchDiv").empty();//清空原数据
createSearchSelected(data.columnData);//添加搜索框下拉列表
createTextInput(data);//生成搜索文本框
}
- 在执行loadData()函数时,调用此函数
function loadData(){
//向Servlet中发送请求,返回的一定是json格式数据
$.post("PageServlet",{"cp":jsParamCP,"ls":jsParamLS,"kw":jsParamKW,"col":jsParamCOL},
function(data){
//创建分页页码
createPageNumber(data);
//创建搜索框
createSearch(data);
//再追加数据前,先清空原表格数据
clearTable();
//返回的数据中包含有一组部门信息,使用的是json数组包装起来的
for(var x=0;x <data.allDepts.length;x++){
//取出每个部门的信息,交给addRow()函数处理,为表格添加数据
addRow(data.allDepts[x].deptno,data.allDepts[x].dname,data.allDepts[x].loc);
}
},"json")
}
- 检索框之中需要两个内容,一个是下拉列表,另一个是输入文本:
- 编写一个创建下拉列表的函数
//添加搜索框下拉列表
function createSearchSelected(columnData){
var selectObj = $("<select></select>");
var columns = columnData.split("|");
for (var i = 0; i < columns.length; i++) {
var temp = columns[i].split(":");
var optionObj = $("<option value='"+temp[0]+"'>"+temp[1]+"</option>");
selectObj.append(optionObj);
if(jsParamCOL == temp[0]){
optionObj.attr("selected",true);
}
}
$("#splitPluginSearchDiv").append(selectObj);
}
- 随后还需要追加一个文本输入框,那么就需要有检索
- 定义一个创建文本输入框的函数
//生成搜索文本框
function createTextInput(data){
var inputobj = $("<input id='searchKw' value='"+data.keyword+"'/>");
var searchBut = $("<input type='button' value='搜索'>");
searchBut.on("click",function(){
//改变模糊查询列和模糊查询值的关键字的值
jsParamCOL = $("#col").val();
jsParamKW = $("#searchKw").val();
loadData();
});
var resultCount = $("<span>共返回"+data.allRecorders+"条数据</span>")
$("#splitPluginSearchDiv").append(inputobj);
$("#splitPluginSearchDiv").append(searchBut);
$("#splitPluginSearchDiv").append(resultCount);
}
- 在loadData()函数中调用createSearch()函数
//规定使用分页组件必须编写koadData()函数
function loadData(){
//向Servlet中发送请求,返回的一定是json格式数据
$.post("PageServlet",{"cp":jsParamCP,"ls":jsParamLS,"kw":jsParamKW,"col":jsParamCOL},
function(data){
//创建分页页码
createPageNumber(data);
//创建搜索框
createSearch(data);
//再追加数据前,先清空原表格数据
clearTable();
//返回的数据中包含有一组部门信息,使用的是json数组包装起来的
for(var x=0;x <data.allDepts.length;x++){
//取出每个部门的信息,交给addRow()函数处理,为表格添加数据
addRow(data.allDepts[x].deptno,data.allDepts[x].dname,data.allDepts[x].loc);
}
},"json")
}
- 最后的效果