開發(fā)中難免要碰到分頁查詢的功能實現. 這個功能個人是比較頭疼, (1)雖然功能簡單, 但實現的嚴謹還是比較費神的. (2)不能環(huán)境下, 一樣的分頁代碼難以滿足, 比如html中和jsp中就不一樣. 同步請求和異步請求有不一樣.
對于一些用于jsp環(huán)境的分頁套路, 個人不是很喜歡, 沒辦法, 鐘愛前后端分離的套路. 于是想找一款基于js的實現的分頁條功能. 無意中發(fā)現下面將要介紹的這款插件. 基本功能完全沒有問題. 但是想要滿足自己的定制化需求還是比較費勁的. 我想這也是前端的通病吧, 變幻莫測. 根本難以一套代碼搞定一切場景.
jquery.pagination.js
這一款比較好用前端分頁jquery插件.
GitHub地址
demo
缺陷
- 作者的初衷設計是想要樣式和功能分離. 這樣還是不錯的, 留給使用充分的定制空間. 然而, 前端最讓我苦惱的就是: (1)定制樣式必須要依賴于插件內部生成的html代碼. (2)繁瑣的樣式文件和配置, 還需要手動設置.
在使用這款插件時, 本來想要借助作者提供的樣式文件的, 結果一看有四五個, 而且無還不知道怎么配置(沒有文檔說明), 再加上還要依賴于jquery... 瞬間就失去了興趣了. 我的要求是, 插件嘛, 一個js, 一個css搞定. 這才叫清爽.
- 個人覺得
bootstrap
的分頁條比較簡潔好看, 但是這款插件不支持.
優(yōu)化
(1)不想學習配置樣式; (2)喜歡bootstrap分頁條.
于是, 想起來, 研究下源碼吧, 看看能不能優(yōu)化下, 實現我的需求.
插件有個參數mode
: (1)fixed
分頁按鈕固定, (2)unfixed
, 分頁按鈕不固定.
源碼長這樣:
既然這樣, 我就想, 不如給你加個mode, 就叫做: bootstrap. 當我如下配置時, 會給出來bootstrap樣式的分頁條.
優(yōu)化代碼片
增加一個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
(回調函數), 發(fā)送表單請求. 請求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" 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>