大千世界,茫茫人海,相识就是一种缘分。若此篇文章对您有帮助,点个赞或点个关注呗!

前言

数据分页也是开发中经常遇到的需求之一。不管运用什么技术,分页无非就是前端分页或后端分页,也就是所谓的假分页与真分页。不过,按照常规来说,最好还是后端分页。假设有数万条数全部返回到前端,前端再进一步逻辑分页,可想而知响应到客户的视图界面需要多长时间。当数据量少的时候,前后端分页都一样,基本没什么区别;数据量过多,强烈建议后端分页。

一、开发环境

  • 前端: Vue 2.0 element-ui组件【版本2.13.0】Pagination 分页组件
  • 后端: SpringBoot2.0   插件PageHelper的jar包【1.2.3】

二、话不多说,先预览效果图
  1、这是最终实现的完整效果图,需要自定义其他的分页栏,可在elemet-ui组件中自己引入相关的代码即可;
在这里插入图片描述
  2、element-ui组件目支持的分页样式,属性和方法这里不做赘述,可前往官网查看引用
在这里插入图片描述
三、VUE纯前端的分页
  前端分页机制:

  1. 首先查出对应接口的所有数据返回至前端;
  2. 结合element组件的分页,获取选中的页码与页大小;
  3. 利用slice()方法可从已有的数组中返回选定的元素:arrayObject.slice(start,end)

代码示例:
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>
Logo

前往低代码交流专区

更多推荐