之前自己在使用这种网站时,经常看到无限加载的效果。
今天正好看到了
这个 Api,就想着试试看如何实现
- getBoundingClientRect
的效果。
- Infinite scroll
在需要无限加载的列表底部,埋下一个隐藏元素。
当不断滑动时,隐藏元素将出现在视窗 (viewport) 里,也就意味着当前浏览的列表已经到底部了。
这时候就需要进行列表加载。
大概的 html 结构如下:
- <div>
- <ulclass="article-list">
- <li>
- 我是文章
- </li>
- <li>
- 我是文章
- </li>
- <li>
- 我是文章
- </li>
- <li>
- 我是文章
- </li>
- <li>
- 我是文章
- </li>
- </ul>
- <divclass="infinite-scroll-signal">
- </div>
- </div>
那么重点就是检测隐藏的无限加载指示器是否出现在视图窗口。
还好,我们有
这个 Api。
- getBoundingClientRect
通过查阅 MDN,得知:
Element.getBoundingClientRect() 方法返回元素的大小及其相对于视口的位置。而除了 width 和 height 外的属性都是相对于视口的左上角位置而言的。
至于兼容性,一片绿,可以放心使用。
Can I Use getboundingclientrect? Data on support for the getboundingclientrect feature across the major browsers from caniuse.com.
getBoundingClientRect() 方法的返回值是一个 DOMRect 对象,这个对象是由该元素的 getClientRects() 方法返回的一组矩形的集合, 即:是与该元素相关的 CSS 边框集合 。
对象的属性如下图所示:
其中的
均是元素自身相对于视图左上角而言的。
- top, left, bottom, right
就
属性而言,很好理解。而
- top, left
则一开始搞的有点懵,后面通过 devtools 观察,发现
- bottom, right
是元素的最底部相对于视图窗口左上角而言的,而
- bottom
则是元素的最右侧相对于视图窗口左上角而言的。
- right
其中
为元素的宽度,
- right-left
则是元素的高度。
- bottom - top
在这里,有两种情况,一个是元素是否出现于视图窗口中,另一种则是元素是否完全出现于视图窗口中。
两种情况的区别在于一个是部分出现,一个是完全出现。
下面我把两种情况都写出来:
- functioncheckIsPartialVisible(element){
- const rect = element.getBoundingClientRect()
- const {
- top,
- left,
- bottom,
- right
- } = rect
- const isPartialVisible = top >= 0 && left >= 0
- return isPartialVisible
- }
- functioncheckIsTotalVisible(element){
- const rect = element.getBoundingClientRect()
- const {
- top,
- left,
- bottom,
- right
- } = rect
- const isTotalVisible = (
- top >= 0
- &&
- left >= 0
- &&
- bottom < document.documentElement.clientHeight
- &&
- right < document.documentElement.clientWidth
- )
- return isTotalVisible
- }
那么问题来了:我们到底选用那种呢?
从无限加载这个业务场景出发,埋在列表最下边的加载触发器都非常小且不可见,因此推荐选用第二种,也就是完全出现于视图窗口的方式。
至于第一种,更适合检测该元素是否已经出现在视图窗口,但并不要求全部出现的情况。
具体可以看我在 jsfiddle 上写的 demo:
无限加载实例
后续更多的则是一些性能优化的事情,比如 debounce 或者 throttle 来减少 scroll 事件调用次数,加入 ajax 加载,loading indicator 等。
那些都是属于具体的业务范围了,这儿不做讨论。
如果你觉得我的文章对你有帮助,请支持我。让我写出更好的文章。
来源: http://www.tuicool.com/articles/zmMbQn3