origin
When I used this kind of website before, I often saw the infinite loading effect.
I happened to see getBoundingClientRect
this API today and wanted to try it out to see how it works Infinite scroll
.
principle
Bury a hidden element at the bottom of the list that needs to be infinitely loaded.
When sliding continuously, hidden elements will appear in the viewport, which means that the currently browsed list has reached the bottom.
At this time, you need to load the list.
The approximate HTML structure is as follows:
<div>
<ul class="article-list">
<li>我是文章</li>
<li>我是文章</li>
<li>我是文章</li>
<li>我是文章</li>
<li>我是文章</li>
</ul>
<div class="infinite-scroll-signal"></div>
</div>
That is: sliding list => hidden infinite loading indicator appears in view => starts loading
Then the point is to detect whether the hidden infinite loading indicator appears in the view window.
Fortunately, we have getBoundingClientRect
this API.
getBoundingClientRect
By consulting MDN, I learned:
The Element.getBoundingClientRect() method returns the size of the element and its position relative to the viewport. Properties other than width and height are relative to the upper left corner of the viewport.
As for compatibility, it’s all green and you can use it with confidence.
<p class="ciu_embed" data-feature="getboundingclientrect" data-periods="future_1,current,past_1,past_2">
Can I Use getboundingclientrect? Data on support for the getboundingclientrect feature across the major browsers from caniuse.com.
</p>
DOMRect object
The return value of the getBoundingClientRect() method is a DOMRect object, which is a collection of rectangles returned by the element's getClientRects() method, that is, a collection of CSS borders related to the element.
The properties of the object are as shown below:
All of them top, left, bottom, right
are relative to the element itself relative to the upper left corner of the view.
In top, left
terms of properties, it's easy to understand. bottom, right
I was a little confused at first, but after observing through devtools, I found that bottom
the bottommost part of the element is relative to the upper left corner of the view window, and right
the rightmost part of the element is relative to the upper left corner of the view window.
where right-left
is the width of the element, bottom - top
and is the height of the element.
Detect whether an element appears in the view window
Here, there are two situations, one is whether the element appears in the view window, and the other is whether the element appears completely in the view window.
The difference between the two situations is that one appears partially and the other appears completely.
Below I write out both situations:
-
section appears in the view window
function checkIsPartialVisible (element) {
const rect = element.getBoundingClientRect()
const {
top,
left,
bottom,
right
} = rect
const isPartialVisible = top >= 0 && left >= 0
return isPartialVisible
}
-
All appear in the view window:
function checkIsTotalVisible (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
}
So the question is: Which one should we choose?
Starting from the business scenario of infinite loading, the loading triggers buried at the bottom of the list are very small and invisible, so it is recommended to use the second method, which is to appear completely in the view window.
As for the first type, it is more suitable for detecting whether the element has appeared in the view window, but does not require all occurrences.
Follow-up
What follows is more performance optimization, such as debounce or throttle to reduce the number of scroll event calls, adding ajax loading, loading indicator, etc.
Those are specific business scopes and will not be discussed here.