分页器上应该有前进与后退按钮,可以向前向后翻页。还要有一组页码,点击页码打开对应的页面。页码如果太多不能全部显示出来,可以只显示当前页的前两个项目,后两个项目,再加上第一页还有最后一页。

分页数据的结构
一般你的应用框架或者系统都有能力给你提供分页显示的数据。这种数据里面会带着内容列表项目,还要包含分页相关的信息,比如数据的一共有多少个,每页显示的数量,当前页是多少,最后一页是多少,或者叫总页数是多少。
下面是我的应用框架(Adonis.js)给我返回来的分页数据:
{
"total": 15,
"perPage": 3,
"page": 1,
"lastPage": 5,
"data": [
{ id: 1, title: '...' },
{ id: 2, title: '...' },
{ id: 3, title: '...' },
]
}- total:内容项目(文章,评论...)的总数。
- perPage:每页显示多少个内容。
- page:当前页码是多少。
- lastPage:一共有多少页。
- data:当前页显示的内容项目数据。
获取当前页数据
使用地址查询符,可以动态地把要显示的页码传递到后端,后端可以根据页码的值从数据为里找出对应的一组数据。比如 /posts 是用来显示内容列表用的,访问 /posts?page=2 这个地址的时候,后端就可以得到查询符里的 page 的值等于 2,根据这个 page 的值找出第二页要显示的数据。
请求的处理方法看起来像这样:
const pageNumber = request.input('page', 1)
const pageSize = 3
const posts = await Post
.query()
.paginate(pageNumber, pageSize)
return view.render('post.index', {
...posts
})pageNumber 的值是从地址查询符里得到的 page 这个参数的值,就是页码。pageSize 是每页要显示的项目数量。接着根据这两个值去查询数据库,获取到当前页需要的数据。把数据交给一个视图去处理。
上一页,下一页
在内容列表视图里面,已经得到了分页数据,其中 data 里面是具体要显示的数据,另外还有分页相关信息,比如 total,perPage,page,lastPage。
上一页
上一页导航链接,应该像这样:
<a href="?page={{ page - 1 }}">上一页</a>比如当前页是 3,这个上一页链接的地址应该就是 ?page=2。在视图里可以使用 page 的值,就是当前正在显示的页面的页码。你也可以先判断了一下,如果当前页面的页码减 1 等于 0,就说明没有上一页的内容,这时链接地址就会变成 #。不然链接就会链向上一页内容。
下一页
下一页导航链接,像这样:
<a href="?page={{ page + 1 }}">Next</a>比如当前页是 3,这个上一页链接的地址应该就是 ?page=4。你也可以做一下判断,如果当前页面的页码减去总共的页数等于 0,就说明没有下一页的内容,这时链接地址就会变成 #。不然链接就会链向下一页内容。
页码
页码链接的关键在于,你不能把所有页码显示全部显示出来,假设你有 100 页内容,你不太可能在内容列表下面显示全部 100 个页码链接。我们只需要显示当前页的前两个,后两个页码,再加上第一个,还有最后一个页码就行了。
一组页码可以看成是一个数字数组,根据这个数组可以先容易把它转换成页码链接。现在的需要解决一个问题,就是得到某个数组项目里的前两个还有它的后两个项目。这里可以练习一下数组的 slice 方法。
先这样:
> const pages = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] undefined > let page = 6 undefined > const lastPage = 10 undefined
然后再试一下 slice 方法:
> pages.slice(page) [ 7, 8, 9, 10 ] > pages.slice(page, page + 2) [ 7, 8 ] > pages.slice(page - lastPage) [ 7, 8, 9, 10 ] > pages.slice(page - lastPage - 3) [ 4, 5, 6, 7, 8, 9, 10 ] > pages.slice(page - lastPage - 3, page) [ 4, 5, 6 ] > pages.slice(page - lastPage - 3, page - 1) [ 4, 5 ]
理解了上面的练习,就解决了创建页码链接的基础部分。下面是我为框架的视图添加的一个全局方法,名字是 pageItems,它的主要作用是生成页码链接数组项目。
View.global('pageItems', (lastPage, page) => {
/**
* make all page items.
* use range method from lodash.
*/
const allPageItems = range(1, lastPage + 1)
/**
* range item number.
*/
const pageItemRange = 2
/**
* page items after current item.
*/
const pageItemAfter = allPageItems.slice(page, page + pageItemRange)
console.log('after: ', pageItemAfter)
/**
* page items before current item.
*/
const pageItemBefore = allPageItems.slice(page - 1 - lastPage - pageItemRange, page - 1)
console.log('before: ', pageItemBefore)
/**
* base page items
*/
let pageItems = [
...pageItemBefore,
page,
...pageItemAfter
]
console.log('pageItems: ', pageItems)
/**
* first and last item
*/
let firstItem = [1]
let lastItem = [lastPage]
if (pageItemRange + 2 < page) {
firstItem = [
...firstItem,
'...'
]
}
if (lastPage - page - 1 > pageItemRange) {
lastItem = [
'...',
...lastItem
]
}
if (pageItemRange + 1 < page) {
pageItems = [
...firstItem,
...pageItems
]
}
if (lastPage - page > pageItemRange) {
pageItems = [
...pageItems,
...lastItem
]
}
return pageItems
})在视图里生成页码链接:
@each(item in pageItems(lastPage, page))
<a href="?page={{ item }}">{{ item }}</a>
@endeach 



评论
太幸福甜蜜了也
7 年 6 个月 以前