幾行代碼摸清楚上拉加載原理

https://www.cnblogs.com/chanwahfung
效果
貼上效果展示:
實(shí)現(xiàn)思路
樣式方面不多贅述,滾動區(qū)域是給固定高度,設(shè)置 overflow-y: auto 來實(shí)現(xiàn)。
接下來看看js方面的實(shí)現(xiàn),其實(shí)也很簡單,觸發(fā)的條件是:可視高度 + 滾動距離 >= 實(shí)際高度 。例子我會使用vue來實(shí)現(xiàn),和原生實(shí)現(xiàn)是一樣的。
可視高度(offsetHeight):通過 dom的offsetHeight獲得,表示區(qū)域固定的高度。這里我推薦通過getBoundingClientRect()來獲取高度,因?yàn)槭褂们罢邥馂g覽器回流,造成一些性能問題。滾動高度(scrollTop):滾動事件中通過 e.target.scrollTop獲取,表示滾動條距離頂部的px實(shí)際高度(scrollHeight):通過 dom的scrollHeight獲得,表示區(qū)域內(nèi)所有內(nèi)容的高度(包括滾動距離),也就是實(shí)際高度
基礎(chǔ)實(shí)現(xiàn)
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('觸底')
????}
}

so easy~
加點(diǎn)細(xì)節(jié)
加點(diǎn)細(xì)節(jié),現(xiàn)在我們希望是離底部一定距離就觸發(fā)事件,而不是等到完全觸底。如果你做過小程序,這和onReachBottom差不多的意思。
聲明一個離底部的距離變量reachBottomDistance
這時候觸發(fā)條件:可視高度 + 滾動距離 + reachBottomDistance >= 實(shí)際高度
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('觸底')
????????}
????}
??}
}

在距離底部100px時成功觸發(fā)事件,但由于100px往下的區(qū)域是符合條件的,會導(dǎo)致一直觸發(fā),這不是我們想要的。
接下來做一些處理,讓其進(jìn)入后只觸發(fā)一次:
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???????????this.isReachBottom?=?false
????????}
????????if(this.isReachBottom){
??????????return
????????}
????????if?(currentHeight?>=?scrollHeight)?{
??????????this.isReachBottom?=?true
??????????console.log('觸底')
????????}
????}
??}
}

優(yōu)化
實(shí)時去獲取位置信息稍微會損耗性能,我們應(yīng)該把不變的緩存起來,只實(shí)時獲取可變的部分
export?default?{
??data(){
????return?{
??????isReachBottom:?false,
??????reachBottomDistance:?100
??????scrollHeight:?0,
??????offsetHeight:?0,
????}
??},
??mounted(){
????//?頁面加載完成后??將高度存儲起來
????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.isReachBottom?=?false
????????}
????????if(this.isReachBottom){
??????????return
????????}
????????if?(currentHeight?>=?this.scrollHeight)?{
??????????this.isReachBottom?=?true
??????????console.log('觸底')
????????}
????}
??}
}
實(shí)現(xiàn)到這里就告一段落,如果你有更好的思路和值得改進(jìn)的地方,歡迎交流~
- END -分享前端好文,點(diǎn)亮?在看?
評論
圖片
表情

