node用express写后端restful接口实战八:分页查询
分页原理
这一集要实现的是数据分页功能。分页功能的实现,是由 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
参数是固定不动的,就是 10
。offset = (当前页数 - 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
,因为现在不仅仅有文章列表
了,还有记录总数
。
接着要做的就是,添加上 offset
和 limit
参数。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
,包含的值分别是 currentPage
、pageSize
和 total
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 条。
http://localhost:3000/articles?currentPage=2&pageSize=3,再来将 currentPage
改为 2
。这样显示的就是第二页的数据了。
分页功能,到这里就已经完美实现了。
完整代码 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});
*/
})