JPA+Springboot实现分页效果
后端
JPA 默认提供了一个分页类:org.springframework.data.domain.Page, 这个分页类已经能够满足各种分页需要了,所以大部分时候用它就足够了。但是除了一点,就是如图所示的,比如当前是第8页,前面要显示3个,后面要显示3个,总共7条分页点,这个类默认就不提供了。
所以我们做了一个 Page4Navigator, 首先对 Page 类进行了封装,然后在构造方法里提供了一个 navigatePages 参数。
navigatePages:导航需要的个数,这里设置为7,就表示如图所示的效果,前面3个,后面3个。
思路:
-
当总页数小于或等于导航页码数时,就遍历现有的页码总数,这种最简单了。
-
当总页数大于导航页码数(7)时,现在当前页
num
为8,就计算出开始数num - navigatePages / 2
和结尾数num + navigatePages / 2
,这种情况下分别为5和11,对开始数5使用for
循环7次,就可以得到一个int
数组变量navigatepageNums
[5,6,7,8,9,10,11],方便前端遍历展示。 -
异常处理:
- 若起始值小于1时,则起始值设置为1,对着起始值循环7次
startNum++
得到数组 - 若结尾值大于总条数时,则结尾值设置为总条数,数组索引设置为6(7-1),对着结尾值循环7次
endNum--
得到数组
- 若起始值小于1时,则起始值设置为1,对着起始值循环7次
工具类Page4Navigator
private void calcNavigatepageNums() {
int navigatepageNums[];
int totalPages = getTotalPages();
int num = getNumber();
//当总页数小于或等于导航页码数时
if (totalPages <= navigatePages) {
navigatepageNums = new int[totalPages];
for (int i = 0; i < totalPages; i++) {
navigatepageNums[i] = i + 1;
}
} else { //当总页数大于导航页码数时
navigatepageNums = new int[navigatePages];
int startNum = num - navigatePages / 2;
int endNum = num + navigatePages / 2;
if (startNum < 1) {
startNum = 1;
//(最前navigatePages页
for (int i = 0; i < navigatePages; i++) {
navigatepageNums[i] = startNum++;
}
} else if (endNum > totalPages) {
endNum = totalPages;
//最后navigatePages页
for (int i = navigatePages - 1; i >= 0; i--) {
navigatepageNums[i] = endNum--;
}
} else {
//所有中间页
for (int i = 0; i < navigatePages; i++) {
navigatepageNums[i] = startNum++;
}
}
}
this.navigatepageNums = navigatepageNums;
}
controller中传入需要的导航数:5页
@GetMapping("/categories")
public Page4Navigator<Category> list(@RequestParam(value = "start", defaultValue = "0") int start, @RequestParam(value = "size", defaultValue = "5") int size) throws Exception {
start = start<0?0:start;
Page4Navigator<Category> page =categoryService.list(start, size, 5); //5表示导航分页最多有5个,像 [1,2,3,4,5] 这样
return page;
}
service中调用封装好的工具类 Page4Navigator
public Page4Navigator<Category> list(int start, int size, int navigatePages) {
Sort sort = new Sort(Sort.Direction.DESC, "id");
Pageable pageable = new PageRequest(start, size,sort);
Page pageFromJPA =categoryDAO.findAll(pageable);
return new Page4Navigator<>(pageFromJPA,navigatePages);
}
前端
思路:
-
开始加载的时候访问
uri
,mounted:function()
调用method
中的list()
方法,传入参数0; -
pagination
和beans
得到数据,取出数据放到分页条中 -
点击最前页时,传入参数
first
到jump(page,vue)
,调用下面的同名函数jump()
中的list(0)
,调用vue
的list(0)
。相当于vue提供的三个方法中间夹带着方法。
构造出导航条
<div class="pageDiv" th:fragment="html">
<nav>
<ul class="pagination">
<li :class="{ disabled: pagination.first }">
<a href="#nowhere" @click="jump('first')">«</a>
</li>
<li :class="{ disabled: !pagination.hasPrevious }">
<a href="#nowhere" @click="jump('pre')">‹</a>
</li>
<li v-for="i in pagination.navigatepageNums">
<a href="#nowhere" @click="jumpByNumber(i-1)" >
{{i}}
</a>
</li>
<li :class="{ disabled: !pagination.hasNext }">
<a href="#nowhere" @click="jump('next')">›</a>
</li>
<li :class="{ disabled: pagination.last }">
<a href="#nowhere" @click="jump('last')">»</a>
</li>
</ul>
</nav>
</div>
$(function(){
var data4Vue = {
uri:'categories',
pagination:{},
beans: []
};
//ViewModel
var vue = new Vue({
el: '#workingArea',
data: data4Vue,
mounted:function(){ //mounted 表示这个 Vue 对象加载成功了
this.list(0);
},
methods: {
list:function(start){
var url = this.uri+ "?start="+start;
axios.get(url).then(function(response) {
vue.pagination = response.data;
vue.beans = response.data.content ;
});
},
jump: function(page){
jump(page,vue); //定义在adminHeader.html 中
},
jumpByNumber: function(start){
jumpByNumber(start,vue);
}
}
});
});
//跳转函数
function jump(page,vue){
if('first'== page && !vue.pagination.first)
vue.list(0);
else if('pre'== page && vue.pagination.hasPrevious )
vue.list(vue.pagination.number-1);
else if('next'== page && vue.pagination.hasNext)
vue.list(vue.pagination.number+1);
else if('last'== page && !vue.pagination.last)
vue.list(vue.pagination.totalPages-1);
}
//跳转函数
function jumpByNumber(start,vue){
if(start!=vue.pagination.number)
vue.list(start);
}