分页操作详解
一、方案一:后端分页
前端向后端发送数据查询请求,可以带上分页参数,后端根据查询参数如数据条数进行查询,对于数据量很大的场景比较友好,每次请求不必一次性查询所有返回给前端。
1.MybatisPlus内置分页插件
在MybatisPlus的扩展服务中有一个接口IService,其中有很多默认方法,可以用来实现分页查询:
default <E extends IPage<T>> E page(E page, Wrapper<T> queryWrapper) {
return getBaseMapper().selectPage(page, queryWrapper);
}
在SSM架构中,我们的Service层接口通常都会继承IService<实体类>,可以调用这个方法进行分页,需要传入两个参数:
- Page分页模型
分页之前我们需要知道返回一个分页数据都应该包含哪些内容?
- 总记录数
- 每页记录数
- 总页数
- 当前页数
- 数据集合
所有的分页请求处理方案都是以这些参数为基础进行封装的
MybatisPlus插件中提供了封装好的Page分页模型,可以在构造函数中传入当前页,每页显示条数,总条数等
public class Page<T> implements IPage<T> {
private static final long serialVersionUID = 8545996863226528798L;
/**
* 查询数据列表
*/
private List<T> records = Collections.emptyList();
/**
* 总数
*/
private long total = 0;
/**
* 每页显示条数,默认 10
*/
private long size = 10;
/**
* 当前页
*/
private long current = 1;
/**
* 排序字段信息
*/
private List<OrderItem> orders = new ArrayList<>();
......
}
可以在此基础上进行改良进一步封装
- QueryWrapper 对象封装的操作类,由MybatisPlus的core包提供,可以理解为封装查询条件的工具
代码示例
QueryWrapper<Student > qw = new QueryWrapper<Student>();
if(StringUtils.isNotBlank(student.getName())){
qw.eq("s.name",student.getName());
}
if(StringUtils.isNotBlank(student.getClassName())){
qw.like("c.name",student.getClassName());
}
方法 | 功能 |
---|---|
qw.eq() | 等于 |
qw.gt() | 大于 |
qw.lt() | 小于 |
qw.between("age", 10, 20) | age在10到20之间 |
qw.like() | 模糊匹配 |
qw.or() | 或者 |
qw.in("属性", 条件,条件) | 符合多个条件的值 |
2.Mybatis--使用PageHelper插件
maven引入:
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
<version>5.2.1</version>
</dependency>
controller层调用:
@ResponseBody
@RequestMapping("/list")
public R listByPage(@RequestParam(defaultValue = "1") Integer pageNum,
@RequestParam(defaultValue = "5") Integer pageSize) {
//查询前,需要调用 PageHelper.startPage()
PageHelper.startPage(pageNum, pageSize);
//在 PageHelper.startPage() 后调用 findAll 就是分页查询(物理分页有 limit)
List<Furn> furnList = furnService.findAll();
//分页查询完之后,可以使用 pageInfo 来包装查询后的结果,
PageInfo pageInfo = new PageInfo(furnList, pageSize);
return R.success().add("pageInfo", pageInfo);
}
二、方案二:前端分页
数据量不大时也可以一次性进行由后端返回所有数据,前端再对要显示的数据进行分页处理,可以减轻对服务器的压力,同样可以处理模糊匹配、条件查询等问题
示例:vue+element
1.使用slice(start, end)方法
//allData为全部数据,tableData是目前表格绑定的数据
this.tableData = this.allData.slice(
(this.page - 1) * this.size,
this.page * this.size
);
this.total=this.allData.length
// 获取表格分页数据
getDataList () {
this.dataList = this.allData.slice(
(this.pageIndex - 1) * this.pageSize,
this.pageIndex * this.pageSize
)
}
注意:
由于实际展示的页面并不是后端发送过来的数据,有可能遇到请求还没有结束就执行了设置tableData的方法,这样方法执行的顺序就不是我们设想的,会导致页面无法正常显示
解决方法:
采用vue的监听器watch对allData(后端发送的数据)进行监听,如果发生了变化就对页面进行刷新设置列表数据
监听器也常用来监听提交表单时判断表单数据有没有被修改,若没有修改就不向后端发送请求
watch: {
allData (newVal, oldVal) {
// console.log('new==',newVal)
// console.log('old==',oldVal)
this.getDataList()
},
updateForm: {
handler (val, old) {
//修改的时候监听该表单,新增不需要
//修改了之后改变变量的值
this.defaultValue++ //判断如果变量大于1,则说明值有改动
if (this.defaultValue > 1) {
this.isEdit = true
}
},
deep: true //深度监听form里的每个对象
}
},
2.前端进行模糊匹配、条件查询
示例:这里我对数据的三个字段:cas、name_cn、name_en进行模糊匹配
search () {
const searchContext = this.dataForm.key
if (this.isBlank(searchContext)) {
this.getDataList()
} else {
this.dataList = this.dataList.filter(item => item.cas.match(searchContext))
if (this.dataList.length === 0) {
this.getDataList()
this.dataList = this.dataList.filter(item => item.name_cn.match(searchContext))
if (this.dataList.length === 0) {
this.getDataList()
this.dataList = this.dataList.filter(item => item.name_en.match(searchContext))
}
}
}
},
isBlank (val) {
return val === null || val === undefined || val === ''
}