在做大部分真实应用的 web 项目过程中,都会有一样不可或缺的需求,那就是分页。Meteor 项目也不例外,同样会有这样的需求,本文给大家介绍的就是一个非常好用的分页包 alethes:pages
。它可以实现简单的根据页数分页,也可以实现强大的滚动分页。内部还支持利用多个 collection 数据进行分页。下面我们就来详细的了解它。 注意:以下内容多是对官方包的一种简述和翻译,如果需要更详细的内容可以参考官方地址。
特性
官网上介绍了很多它的特性,由于我的英文不是很好,我只能翻译我们大家非常关注的点。
- 仅 subscribe 当前页需要的数据,并不是一次性 sub 所有数据
- 本地缓存,获取过的数据本地存储,避免返回时重新获取
- 在加载当前页过程中,预取下一页的数据,确保下一页的时候无缝过度
- 多个集合产生一个分页数据
- 支持
bootstrap 2/3
的分页导航模版 - 支持
iron-router
包 - 页面无限滚动加载特效
安装
1 | meteor add alethes:pages |
官网
atomsphere - https://atmospherejs.com/alethes/pages/ github - https://github.com/alethes/meteor-pages/
Demo 演示
基本的分页 - http://pages.meteor.com/ 表格 (快速渲染) - http://pages-table.meteor.com/ 多个 collection 自动刷新 - http://pages-multi.meteor.com/ 滚动加载效果 - http://pages3.meteor.com/
使用
要使用这个包的功能非常简单,首先用你要实现分页的 collection 生成一个 PlayersPages 分页对象。 这里假设之前已经存在一个 Players 的 collection,你需要对它的数据进行分页显示,我们按如下方式对他下手即可。
1 | // 原有存放数据的 collection |
上面的代码可以看到,我们指定了分页所使用的模版名字叫 playersTemplate
,此时,我们只需要在增加一个这样的模版即可。
1 | <template name="playersTemplate"> |
新建的模版中再导入另外两个模版 pages
和 pagesNav
,这个两个模版是分页包 alethes:pages
给我们创建的,用来显示数据用。如此这样添加后,playersTemplate 模版就可以分页显示 Players collection 的数据了。
个性化
但具体每页显示多少数据、显示数据的样式如何定义、分页导航按钮能不能换成滚动屏幕自动加载瀑布流的方式?等等类似的问题,这个包都提供了解决方案。我们先来看一下它比较重要的几个参数,用一个我们已经使用到项目中的代码片段+注释的方式,来给大家演示这个包的各种参数(更多参数可以参考 github 上的介绍)。
1 | this.ProductPages = new Meteor.Pagination(Products, { |
以上时参考官方给出的无限滚动模式下所使用到的参数,其中 infiniteTrigger
参数我在使用过程中遇到了很多问题。第一个问题就是滚动条滚动到 0.8 的位置后,数据不会自动继续加载。修正了第一个问题后,随后出现的问题时滚动条并非到 0.8 的位置才加载数据,而是我滚动条只要一动,下一页的数据就自动加载出来了,这样明显不对。 我们通过分析处理 infiniteTrigger
参数的源代码来判断问题出在了哪里,请看代码和注释。
1 | Pages.prototype.setInfiniteTrigger = function() { |
分析过代码后,我得出判断,第一个问题时由于我们页面中有一个很大的 div 当作 body 来用,滚动的时候实际时 div 的滚动条在滚动,而 body 的滚动条一直在 0 的位置,所以无论你看到的 div 的滚动条滚动到了哪里,下一组数据都不会继续加载。 在第一个问题解决完以后,再继续分析第二个问题,首先清楚两个概念。 document.body.offsetHeight - body 整个页面的高度,一般是页面中所有元素加起来的高度之和。 window.innerHeight - 可视的高度,当前浏览器显示了多少内容,这些内容的高度之和。 我分别在页面中打印了一下 window.innerHeight
的值和 document.body.offsetHeight
的值,赫然发现两个值时相等的,所以导致我滚动条刚刚开始滚动的时候,window.innerHeight + window.scrollY
一定大于 document.body.offsetHeight * infiniteTrigger
的值。知道原因了,如何解决呢?为什么 document.body.offsetHeight
的值与 window.innerHeight
的值一样大呢?不应该是页面所有元素的高度吗?在分析别人的代码对比后发现,原来我们的 body 被设定了一个 css 样式为 height: 100vh;
,该属性的意思就是将 body 的高度设定为可视的高度,所以 body 的高度与 window.innerHeight
就没什么区别了,最终导致了如上问题,将这个 css 修改为 height: 100%
即可解决问题。
总结
这个包需要研究的地方还有很多,希望我介绍的内容能帮助大家在后期开发 Meteor 项目减少一些麻烦,一起努力共勉。