大千世界,茫茫人海,相识就是一种缘分。若此篇文章对您有帮助,点个赞或点个关注呗!
数据分页也是开发中经常遇到的需求之一。不管运用什么技术,分页无非就是前端分页或后端分页,也就是所谓的假分页与真分页。不过,按照常规来说,最好还是后端分页。假设有数万条数全部返回到前端,前端再进一步逻辑分页,可想而知响应到客户的视图界面需要多长时间。当数据量少的时候,前后端分页都一样,基本没什么区别;数据量过多,强烈建议后端分页。
✍一、开发环境
✍二、话不多说,先预览效果图
1、这是最终实现的完整效果图,需要自定义其他的分页栏,可在elemet-ui组件中自己引入相关的代码即可;
2、element-ui组件目支持的分页样式,属性和方法这里不做赘述,可前往官网查看引用
✍三、VUE纯前端的分页
前端分页机制:
代码示例:
paging.vue(以table表格为例)
<el-table
border
//此处通过slice方法显示指定区间大小的数据
:data="tableData.slice((currentPage-1)*pagesize,currentPage*pagesize)"
:height="tableHeight"
style="width: 100%"
>
<el-table-column prop="name1" align="center" label="项目名称1" min-width="10%"></el-table-column>
<el-table-column prop="name2" align="center" label="项目名称2" min-width="10%"></el-table-column>
</el-table>
<div>
<el-pagination
//改变页码条数触发的方法
@size-change="handleSizeChange"
//改变页码触发的方法
@current-change="handleCurrentChange"
//当前页数
:current-page="currentPage"
//每页显示个数的数组
:page-sizes="[5, 10, 20, 40]"
//每页显示个数
:page-size="pagesize"
layout="total, sizes, prev, pager, next, jumper"
//总条目数
:total="tableData.length"
></el-pagination>
</div>
paging.js(列举核心代码)
export default {
data() {
return {
tableData: [],
currentPage: 1, // 初始页
pagesize: 10, //每页的数据
tableHeight: 0,//table表格的高度
},
created() {
this.getTableList();
},
methods: {
getTableList() {
getTableList(this).then(res => {
if (res.success) {
//获取后台返回的列表集合
this.tableData = res.data;
}
});
},
//pageSize(页码条数)改变时会触发
handleSizeChange(val) {
this.pagesize = val;
},
//currentPage(跳转页码)改变时会触发
handleCurrentChange(val) {
this.currentPage = val;
},
}
✍三、Java纯后端实现分页
后端分页的核心:pagehelper分页的插件,国内非常优秀的一款开源的mybatis分页插件
1. pom.xml文件引入对应的jar包,我用的是1.2.3jar包
<!---PageHelper-->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
<version>1.2.3</version>
</dependency>
2. 创建Page.java的model分页基础类和分页查询返回数据model类,用以接收前端传递的分页参数
import com.bnl.util.FieldTransform;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import java.io.Serializable;
import lombok.Data;
@ApiModel(description = "分页基础模型")
@Data
public class Page implements Serializable {
@ApiModelProperty(value = "页码", example = "1")
private int page;
@ApiModelProperty(value = "每页显示的条数", example = "100")
private int limit;
@ApiModelProperty(value = "排序字段", example = "name")
private String sort;
//如果需要利用字段进行排序,则需将该字段按照驼峰命名法规范转换为数据库字段进行排序
public String getSort() {
String[] arr ;
if (sort != null && !"".equals(sort) && (arr = sort.split(" ")).length == 2) {
return FieldParser.databaseField(arr [0]) + " " + arr [1];
}
return sort;
}
}
@Data
@ApiModel("分页查询返回数据模型")
public class PageModel<T> extends Page {
@ApiModelProperty(value = "总页数", example = "50")
private long totalPages;
@ApiModelProperty(value = "总记录数", example = "10000")
private long totalRecords;
@ApiModelProperty(value = "分页数据")
private List<T> data;
}
FieldTransform.java(Java属性值和数据库字段转的换工具类, 依据驼峰命名规范进行转换)
package com.bnl.core.util;
/**
* @author:bnl
* @date 2020/3/18
**/
public final class FieldTransform{
public static String databaseField(String str) {
if (str == null || "".equals(str)) {
throw new IllegalArgumentException("字段名称不符合!");
}
char[] chars = str.toCharArray();
StringBuilder fieled= new StringBuilder();
for (int i = 0; i < chars.length; i++) {
if (Character.isUpperCase(chars[i])) {
fieled.append("_").append(String.valueOf(chars[i]).toLowerCase());
} else {
fieled.append(chars[i]);
}
}
return fieled.toString();
}
}
3. 创建dataList.java的业务实现类,核心步骤,开始执行分页操作
具体的Controller控制类、service接口,我就省略了,因为跟平常开发是一样的,跟分页也没什么关系。只列举核心代码,同样可以解决我们的问题
切记:PageHelper只对紧跟着的第一个SQL语句起作用
import com.github.pagehelper.PageHelper;
@Autowired
private ListMapper listMapper;
@Override
public ResponseModel<PageModel<model>> dataList(Page page) {
//核心步骤,切记一定要写在执行查询sql语句的最前边,否则无法执行分页,因为插件就是这么规定的
PageHelper.startPage(page.getPage(), page.getLimit(), page.getSort());
//将需要进行分页的List集合,一定要紧跟PageHelper,否则无法实现分页。因为第一次我就没有紧跟
//其后,导致一直无法分页
List<model> modelList= listMapper.getList();
//ModelFactory是我定义的一个公共基类,用以分装分页之后的数据及一些相应的参数,
// 底下会有该类ModelFactory的详细信息
//我简写了一步PageInfo<> pageInfo = new PageInfo<>(modelList),
//其实就是对查询出来的List进行处理,可以查看源码
return Message.success(ModelFactory.buildPage(new PageInfo<>(modelList)));
}
ModelFactory.java 公共基类
public class ModelFactory {
public static <T> PageModel<T> buildPage(PageInfo<T> pageInfo) {
//创建分页查询的返回model类
PageModel<T> model = new PageModel();
//封装当前页码
model.setPage(pageInfo.getPageNum());
//封装每页显示的条数
model.setLimit(pageInfo.getPageSize());
//封装查询的总页数(未分页的数据)
model.setTotalPages((long)pageInfo.getPages());
//封装查询的总记录数(未分页的数据)
model.setTotalRecords(pageInfo.getTotal());
//封装分页后的List集合
model.setData(pageInfo.getList());
return model;
}
}
最后将PageInfo.java的源码加以注释,让大家更清晰的了解该类的成员变量信息
public class PageInfo<T> implements Serializable {
private static final long serialVersionUID = 1L;
//页码,从1开始
private int pageNum;
//页大小
private int pageSize;
//当前页的数量
private int size;
//由于startRow和endRow不常用,不做描述
private int startRow;
private int endRow;
//总记录数
private long total;
//总页数
private int pages;
//分页后的结果集
private List<T> list;
//前一页
private int prePage;
//下一页
private int nextPage;
//是否为第一页
private boolean isFirstPage;
//是否为最后一页
private boolean isLastPage;
//是否有前一页
private boolean hasPreviousPage;
//是否有下一页
private boolean hasNextPage;
//导航页码数
private int navigatePages;
//所有导航页号
private int[] navigatepageNums;
private int navigateFirstPage;
private int navigateLastPage;
4. 回到前端界面,大概描述一下请求的触发及参数的封装
后端定义了Page的model类,用以接收前端传递过来的参数,相应的我们必须按照后端的model封装请求的参数。
export default {
data() {
return {
tableHeight: 0,//table表格高度
pageModel: {
page: 1,//默认当前页码
limit: 5,//默认每页的数量
total: 0//返回的总记录数(未分页)
}
};
created() {
this.getList(this.pageModel);
},
//获取记录
getList(page) {
getList(this,page).then(res => {
if (res.success) {
//回显总记录数
this.pageModel.total = Number(res.data.totalRecords);
}
});
}
},
//显示条目个数改变时操作函数
handleSizeChange(pageSize) {
this.pageModel.limit = pageSize;
//重新调用getList()向后台发出请求,获取最新分页的数据
this.getList(this.pageModel);
},
//页码改变时操作函数
handleCurrentChange(currentpage) {
this.tableLoading = true;
this.pageModel.page = currentpage;
//重新调用getList()向后台发出请求,获取最新分页的数据
this.getList(this.pageModel);
},
}
只列出vue界面分页组件的代码块
<div>
<el-pagination
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
:current-page="pageModel.page"
:page-sizes="[5, 10, 20, 40]"
:page-size="pageModel.limit"
layout="total, sizes, prev, pager, next, jumper"
:total="pageModel.total"
></el-pagination>
</div>