分页器上应该有前进与后退按钮,可以向前向后翻页。还要有一组页码,点击页码打开对应的页面。页码如果太多不能全部显示出来,可以只显示当前页的前两个项目,后两个项目,再加上第一页还有最后一页。
分页数据的结构
一般你的应用框架或者系统都有能力给你提供分页显示的数据。这种数据里面会带着内容列表项目,还要包含分页相关的信息,比如数据的一共有多少个,每页显示的数量,当前页是多少,最后一页是多少,或者叫总页数是多少。
下面是我的应用框架(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
评论
太幸福甜蜜了也
6 年 7 个月 以前