🦄 2024 独立开发者训练营,一起创业!查看介绍 / 立即报名(剩余10个优惠名额) →

内容分页器功能的设计开发思路(Pagination)

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

分页数据的结构

一般你的应用框架或者系统都有能力给你提供分页显示的数据。这种数据里面会带着内容列表项目,还要包含分页相关的信息,比如数据的一共有多少个,每页显示的数量,当前页是多少,最后一页是多少,或者叫总页数是多少。

下面是我的应用框架(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 里面是具体要显示的数据,另外还有分页相关信息,比如 totalperPagepagelastPage

上一页

上一页导航链接,应该像这样:

<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

评论

太幸福甜蜜了也

微信好友

用微信扫描二维码,
加我好友。

微信公众号

用微信扫描二维码,
订阅宁皓网公众号。

240746680

用 QQ 扫描二维码,
加入宁皓网 QQ 群。

统计

15260
分钟
0
你学会了
0%
完成

社会化网络

关于

微信订阅号

扫描微信二维码关注宁皓网,每天进步一点