首页 > 技术文章 > node用express写后端restful接口实战八:分页查询

chenxi188 2020-10-20 11:51 原文

分页原理

这一集要实现的是数据分页功能。分页功能的实现,是由 SQL 语句中 limit 的两个参数来实现的。大家一起来看一个表格,先假设每页要显示 10 条数据。

当前页数(currentPage) 从哪里开始(offset) 每页显示多少条(pageSize)
1 0 10
2 10 10
3 20 10
  • 第一页,要从头开始,就是从 0 开始,往后找 10 条数据。这就是第一页要显示的内容。
  • 第二页,就从 10 开始,还是再往后找 10条数据
  • 其他依次类推了。

大家仔细观察下这个表格,动动你聪明的小脑袋。看下中间这个参数 offset,和其他两个参数之间的关系。

offset =   (currentPage - 1) * pageSize

我给大家一个公式,大家看看是不是对的。其中 pageSize 参数是固定不动的,就是 10offset = (当前页数 - 1) * 每页条数。如果你搞清楚了这个规律,现在咱们就可以正式来写分页相关代码了。

分页实现

第一步:当前页数(currentPage)

先来定义下 当前页数(currentPage),如果用户传了这个参数,那就以用户传的为准。如果用户没传,那就默认是 第一页。另外,因为用户传递过来的数据,都是字符串,所以咱们用 parseInt 转换一下。

var currentPage = parseInt(req.query.currentPage) || 1;

这种写法,可能有的同学感觉比较陌生,其实它就相当于

var currentPage = parseInt(req.query.currentPage);
if (!currentPage) {
    currentPage = 1;
}

这是这种写法,不够简洁,所以我们就换成了上面,这种 短路 的写法了。

第二步:每页显示多少条(pageSize)

接着来定义,每页显示多少条(pageSize)。和上面一样的,如果用户不传递参数过来,也给它一个默认值。因为咱们数据库里的数据比较少,一共也只插入了 4 条进去,就让它默认,每页显示两条数据。

var pageSize = parseInt(req.query.pageSize) || 2;

第三步:findAndCountAll、offset 与 limit

这两个参数定义好了以后,现在就要来调整查询部分的代码了。第一个是要将 findAll 改为 findAndCountAll,区别是 findAndCountAll 能返回总的记录数。接收值的 articles 改为 result,因为现在不仅仅有文章列表了,还有记录总数

接着要做的就是,添加上 offsetlimit 参数。offset 对应的值,就是刚才咱们研究出来的计算公式。而 limit 就是 pageSize

var result = await models.Article.findAndCountAll({
    order:[['id', 'DESC']],
    where: where,
    offset: (currentPage - 1) * pageSize,
    limit: pageSize
});

第四步:响应出分页的 json

查询完成后,最后要做的就是响应出json格式了。先来看看, result 里有些什么东西。

return res.json(result);

模糊查询

  • count 里,保存的就是记录总数了,咱们数据库一共就是只有 4 条记录
  • rows 里,存的才是文章列表。

看到结构后,现在先屏蔽掉调试的代码。

res.json 里,先把 articles 的值,改为 result.rows,这样文章列表就有了。

第五步:返回分页数据

至于分页,一般用 Element UI 这类框架,来实现前端分页,就需要三个参数。先来定义一个 pagination,包含的值分别是 currentPagepageSizetotal

res.json({
       articles: result.rows,
       pagination: {
           currentPage: currentPage,
           pageSize: pageSize,

           // 一共有多少条记录
           total: result.count
       }
   });

测试

整体代码就已经完成了,现在来尝试查询一下看看。http://localhost:3000/articles

分页查询

果然,可以看到分页相关的参数了。

再来分别尝试下其他分页参数,http://localhost:3000/articles?currentPage=1&pageSize=3,当前是第一页,每页显示 3 条。

分页查询2

http://localhost:3000/articles?currentPage=2&pageSize=3,再来将 currentPage 改为 2。这样显示的就是第二页的数据了。

分页查询3

分页功能,到这里就已经完美实现了。

完整代码 routes/articles.js


router.get('/',async function(req,res,next){
	// res.json({hello:'sky'})	
	// 普通写法读取文章数据
	/*models.Article.findAll().then(articles=>{
		res.json({articles:articles});
	})*/
	
	//定义模糊查询对象
	var where={}; //搜索空对象
	var title=req.query.title; //获取搜索标题
	//如果请求参数包含title则向where里添加一个模糊查询的属性
	if(title){
		where.title={
			[Op.like]:"%" + title + "%"
		}
	}

	// 分页定义
	// 当前页是第几页
	var currentPage = parseInt(req.query.currentPage) || 1;
	//每页面显示多少条数据
	var pageSize = parseInt(req.query.pageSize) || 2;
	var result = await models.Article.findAndCountAll({
	    order:[['id', 'DESC']],
	    where: where,
	    offset: (currentPage - 1) * pageSize,
	    limit: pageSize
	});
	// return res.json(result);
	return res.json({
       articles: result.rows,
       pagination: {
           currentPage: currentPage,
           pageSize: pageSize,

           // 一共有多少条记录
           total: result.count
       }
   });




	/*异步读取文章数据
	var articles=await models.Article.findAll({
		// order:[['id','DESC']], //数据按id降序排列
		order:[['id','ASC']], //正序排列,默认方式
		where:where,
	});
	res.json({articles:articles});
	*/

})


推荐阅读