Effect
Paste the effect display:
Implementation ideas
In terms of style, we don't need to elaborate. The scrolling area is set to a fixed height. Set overflow-y: auto to achieve this.
Next let's look at the implementation of js, which is also very simple. The trigger condition is: visible height + rolling distance > = actual height. I will use vue to implement the example, just like the native implementation.
- Offset height: obtained through the offset height of dom, indicating the fixed height of the region. Here I recommend getBoundingClientRect() to get height, because using the former will cause browser reflow and some performance problems.
- Scrolltop: obtained through e.target.scrollTop in the scrolling event, indicating the distance px between the scroll bar and the top
- Actual height: obtained through the dom's scrollHeight, indicating the height of all contents in the area (including the rolling distance), that is, the actual height
Foundation realization
onScroll(e) { let scrollTop = e.target.scrollTop let scrollHeight = e.target.scrollHeight let offsetHeight = Math.ceil(e.target.getBoundingClientRect().height) let currentHeight = scrollTop + offsetHeight if (currentHeight >= scrollHeight) { console.log('Touch bottom') } }
so easy~
Add details
Add some details. Now we hope to trigger the event a certain distance from the bottom, rather than wait until the bottom is completely reached. If you've done an applet, it's about the same as onreach button.
Declare a distance variable from the bottom
At this time, the triggering condition: visual height + rolling distance + reach bottomdistance > = actual height
export default { data(){ return { reachBottomDistance: 100 } }, methods: { onScroll(e) { let scrollTop = e.target.scrollTop let scrollHeight = e.target.scrollHeight let offsetHeight = Math.ceil(e.target.getBoundingClientRect().height) let currentHeight = scrollTop + offsetHeight + this.reachBottomDistance if (currentHeight >= scrollHeight) { console.log('Touch bottom') } } } }
The event is triggered successfully when it is 100px from the bottom, but because the area below 100px is qualified, it will trigger all the time, which is not what we want.
Next, do some processing to make it trigger only once after entering:
export default { data(){ return { isReachBottom: false, reachBottomDistance: 100 } }, methods: { onScroll(e) { let scrollTop = e.target.scrollTop let scrollHeight = e.target.scrollHeight let offsetHeight = Math.ceil(e.target.getBoundingClientRect().height) let currentHeight = scrollTop + offsetHeight + this.reachBottomDistance if(currentHeight < scrollHeight && this.isReachBottom){ this.isReachBottom = false } if(this.isReachBottom){ return } if (currentHeight >= scrollHeight) { this.isReachBottom = true console.log('Touch bottom') } } } }
optimization
Getting location information in real time will slightly degrade performance. We should cache the unchanged information and only get the variable part in real time
export default { data(){ return { isReachBottom: false, reachBottomDistance: 100 scrollHeight: 0, offsetHeight: 0, } }, mounted(){ // Store height after page loading let dom = document.querySelector('.comment-area .comment-list') this.scrollHeight = dom.scrollHeight this.offsetHeight = Math.ceil(dom.getBoundingClientRect().height) }, methods: { onScroll(e) { let scrollTop = e.target.scrollTop let currentHeight = scrollTop + this.offsetHeight + this.reachBottomDistance if(currentHeight < this.scrollHeight && this.isReachBottom){ this.isReachBottom = false } if(this.isReachBottom){ return } if (currentHeight >= this.scrollHeight) { this.isReachBottom = true console.log('Touch bottom') } } } }
If you have a better idea and something to improve, welcome to exchange~