开发中难免要碰到分页查询的功能实现. 这个功能个人是比较头疼, (1)虽然功能简单, 但实现的严谨还是比较费神的. (2)不能环境下, 一样的分页代码难以满足, 比如html中和jsp中就不一样. 同步请求和异步请求有不一样.
对于一些用于jsp环境的分页套路, 个人不是很喜欢, 没办法, 钟爱前后端分离的套路. 于是想找一款基于js的实现的分页条功能. 无意中发现下面将要介绍的这款插件. 基本功能完全没有问题. 但是想要满足自己的定制化需求还是比较费劲的. 我想这也是前端的通病吧, 变幻莫测. 根本难以一套代码搞定一切场景.
jquery.pagination.js
这一款比较好用前端分页jquery插件.
GitHub地址
demo
image.png
缺陷
- 作者的初衷设计是想要样式和功能分离. 这样还是不错的, 留给使用充分的定制空间. 然而, 前端最让我苦恼的就是: (1)定制样式必须要依赖于插件内部生成的html代码. (2)繁琐的样式文件和配置, 还需要手动设置.
在使用这款插件时, 本来想要借助作者提供的样式文件的, 结果一看有四五个, 而且无还不知道怎么配置(没有文档说明), 再加上还要依赖于jquery... 瞬间就失去了兴趣了. 我的要求是, 插件嘛, 一个js, 一个css搞定. 这才叫清爽.
- 个人觉得
bootstrap
的分页条比较简洁好看, 但是这款插件不支持.
优化
(1)不想学习配置样式; (2)喜欢bootstrap分页条.
于是, 想起来, 研究下源码吧, 看看能不能优化下, 实现我的需求.
插件有个参数mode
: (1)fixed
分页按钮固定, (2)unfixed
, 分页按钮不固定.
源码长这样:
既然这样, 我就想, 不如给你加个mode, 就叫做: bootstrap. 当我如下配置时, 会给出来bootstrap样式的分页条.
优化代码片
增加一个case分支.
case 'bootstrap': // +:引入bootstrap的分页导航条 Nisus 2018-1-31 15:21:51 bug: 目前设置首页和末页后, 下一页有bug, 当前页为1时, 下一页不往下走.
//bootstrap分页的起始
html += '<nav aria-label="Page navigation"><ul class="pagination">';
if (opts.coping) {
var home = opts.coping && opts.homePage ? opts.homePage : '1';
//首页
// html += '<a href="javascript:;" data-page="1">' + home + '</a>';
var startCls = '';
if (current == 1) {
startCls = 'active';
}
html += '<li class="' + startCls + '"><a href="javascript:;" data-page="1">' + home + '</a></li>';
}
//上一页
// html += '<li>\n' +
// ' <a class="' + opts.prevCls + '" href="javascript:;" aria-label="Previous">' + opts.prevContent +
// ' </a>' +
// ' </li>';
html += '<li><a href="javascript:;" class="' + opts.prevCls + '" aria-label="Previous">' + opts.prevContent + '</a></li>';
// <span aria-hidden="true">' + opts.prevContent + '</span>
var start = current > opts.count - 1 ? current + opts.count - 1 > pageCount ? current - (opts.count - (pageCount - current)) : current - 2 : 1;
var end = current + opts.count - 1 > pageCount ? pageCount : start + opts.count;
for (; start <= end; start++) {
if (start != current) {
html += '<li><a href="javascript:;" data-page="' + start + '">' + start + '</a></li>';
} else {
html += '<li class="active"><a href="javascript:;" data-page="' + start + '">' + start + '</a></li>';
}
}
//下一页
html += '<li><a href="javascript:;" class="' + opts.nextCls + '" aria-label="Next">' + opts.nextContent + '</a></li>';
// html += '<li>' +
// ' <a class="' + opts.nextCls + '" href="javascript:;" aria-label="Next">' +
// ' <span aria-hidden="true">' + opts.nextContent + '</span>' +
// ' </a>' +
// ' </li>';
if (opts.coping) {
var _end = opts.coping && opts.endPage ? opts.endPage : pageCount;
//末页
var endCls = '';
if(current===pageCount) {
endCls = 'active';
}
html += '<li class="' + endCls + '"><a href="javascript:;" data-page="' + pageCount + '">' + _end + '</a></li>';
// html += '<a href="javascript:;" data-page="' + pageCount + '">' + _end + '</a>';
}
// //尾部
html += '</ul></nav>';
break;
应用
页面使用list.jsp
, 后台分页使用mybatis的PageHelper
插件实现分页查询数据.
流程:
- 第一次请求
list.jsp
页面时, 分页数据采用默认值, 后台参数封装类叫做BrandQuery
, 该pojo设置分页默认值(当前页1, 页大小9). 服务器响应页面后, 页面数据位加载数据, 分页条处加载分页条. 关键点: 后台需要回传当前页, 让分页插件接收到, 这样才能让当前分页按钮高亮. - 之后, 点击分页按钮后, 进入插件中配置的
callback
(回调函数), 发送表单请求. 请求list.jsp
. 实现更新数据.
前端
引入插件
下载插件包. 然后在jsp页面中引入.
- jquery.js
- jquery.pagination.js
- bootstrap的css
<!--使用jquery.pagination.js插件的bootstrap分页条样式需要引用的js,css文件-->
<script type="text/javascript" src="/js/jquery-1.8.3.min.js"></script>
<script type="text/javascript" src="/js/plugins/jquery.pagination.js"></script>
<!-- 最新版本的 Bootstrap 核心 CSS 文件 -->
<link rel="stylesheet" href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
<!--///使用jquery.pagination.js插件的bootstrap分页条样式需要引用的js,css文件-->
数据位接受后台数据
响应的数据, 图省事, 也封装在了BrandQuery
类中.
分页位置代码
<!-- START: 分页导航条 -->
<div class="page-nav"></div>
<script type="text/javascript">
//记录当前页
var current = ${brandQuery.current};
current = current === null?1:current;
$('.page-nav').pagination({
mode:'bootstrap', //生成bootstrap风格的分页条
/* ABANDON: 会有bug, 导致'下一页'在当前页为1时失效
coping: true,
homePage: '首页',
endPage: '末页',
*/
prevContent: '上页',
nextContent: '下页',
jump:true,
current:current,
callback:function (api) {
$('#ipt_current').val(api.getCurrent());
$('#queryFormId').submit();
}
})
</script>
<!-- END: 分页导航条 -->
后台
controller
/**
* 跳转至 ./brand/*
*/
@RequestMapping(value = {"/brand/{page}"})
public String gotoBrandtPage(@PathVariable String page, BrandQuery brandQuery, Model model){
page = "brand/"+page; //不能加 / 了, xml中配置的前缀已经含有 /
log.debug("跳转至:{}", page);
// 查询数据
// 给默认值
// 默认显示出 is_display = 1 i.e. 可见的
if (brandQuery.getIs_display() == null) {
brandQuery.setIs_display(1);
}
// List<Brand> brands = brandService.queryBrandByNoPage(brandQuery);
brandQuery = brandService.queryBrandByPage(brandQuery);
model.addAttribute("brandQuery", brandQuery);
//查询条件的回显
model.addAttribute("name", brandQuery.getName());
model.addAttribute("is_display", brandQuery.getIs_display());
return page;
}
service
public BrandQuery queryBrandByPage(BrandQuery brandQuery) {
//开启分页查询
PageHelper.startPage(brandQuery.getCurrent(), brandQuery.getShowData());
//仍然借用正常非分页查询的mapper方法
List<Brand> brands = brandMapper.queryBrandByNoPage(brandQuery);
/*!为了最大限度让用户以前的查询代码丝毫不用变, 改查list就查list!
* 想获取分页信息, 使用包装类即可. 若不嫌麻烦, 也可以修改mapper.xml, 让其返回Page<>对象*/
//获取分页信息
// PageInfo<Brand> pageInfo = new PageInfo<>(brands);
// int pageCount = pageInfo.getPageNum();
Page page = (Page) brands;
brandQuery.setPage(page);
brandQuery.setCurrent(page.getPageNum());
return brandQuery;
}
效果
分页后效果不足
- 存在bug, 增加
首页
和末页
按钮后,下一页
的按钮在当前页为1时失效. - 分页条样式有缺陷, 比如效果图中的,
跳转
非常难看.
附
PageHelper
依赖
我觉的只是个设计精妙的插件. 你可以在原有的dao层代码丝毫不动的情况下, 实现分页功能. 即你不需要为了分页, 而修改mapper接口和mapper.xml. 只需要在查询前, 加上 PageHelper.startPage(...)
.
<!-- pagehelper -->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
<version>4.1.1</version>
</dependency>
网友评论