如何实现无限滚动
簡介
無限滾動對我們來說已經是很常見的功能了,具體表現為當頁面滾動到某個位置時就自動加載數據,本文將探討無限滾動的實現原理以及優化。
原理
我們先看看最簡單的無限滾動的例子:
function fetchData() {fetch(path).then(res => doSomeThing(res.data)); }window.addEventListener('scroll', fetchData);上面就是無限滾動最簡單的例子啦~
其實就是監聽 window 對象的 scroll 事件,然后再觸發獲取數據的函數~
然而,上面的例子中還有很多問題,其中最大的問題就是 獲取數據的函數(以后叫 fetch 函數)沒有觸發條件, 我們還需要不斷優化,才能在生產環境下使用。
添加觸發條件
我們先想想,一般情況下,fetch 函數的觸發條件有哪些呢 ?
在 fetch 過程中不能重復觸發
沒有更多數據的時候不能再觸發
屏幕距離容器邊緣 xxx 的時候觸發
前兩點很好處理,只要加個 isLoading 和 isEnd 的變量就可以了。
添加這兩個變量之后,我們的代碼就變成下面的樣子啦:
第三點對不熟悉 DOM 的童鞋來說就有點難度了~
計算屏幕與容器邊緣的距離
我們以計算屏幕底部與容器底部邊緣為例:
如果有 api 可以直接得到元素底部與屏幕底部的距離就最好啦,可以省去麻煩,但實際上并沒有這樣的 api。
然而,我們可以通過瀏覽器提供的兩個 api,計算出元素底部與屏幕底部之間的距離。
第一個 api 是 window.innerHeight,它返回的是屏幕(viewport)高度。
第二個 api 就是 Element.getBoundingClientRect ,這個方法用來計算元素邊緣與屏幕(viewport)之間的距離。
需要提醒一下,Element.getBoundingClientRect 會得到這么一個類 Object 對象:
可以看看下面這圖:
+------> +--------------------------------------------------------+| | document.body || | || | | body.getBoundingClientRect().top || | || | || +--------------------------------------------------------+| | browser x |+------> +--------------------------------------------------------+ <--+| | window | || | | || | | || | | || | | || | | || | | | window.innerHeight | || | | || | | || | body.getBoundingClientRect().bottom| | | || | | || | | || | | || | | |+------> +--------------------------------------------------------+ || | || | || | || | || | || | |+--------------------------------------------------------+ <--+有了這兩個 api,我們很容易就可以計算出元素底部邊緣與屏幕底部邊緣的位置啦~
我們再修改下我們的代碼:
var isLoading = false; var isEnd = false; var triggerDistance = 200;function fetchData() {var distance = container.getBoundingClientRect().bottom - window.innerHeight;if ( !isLoading && !isEnd && distance < triggerDistance ) {isLoading = true;fetch(path).then(res => {isLoading = false;res.data.length === 0 && isEnd = true;doSomething(res.data);});}} window.addEventListener('scroll', fetchData);修改之后,當容器底部與屏幕底部距離小于 200 的時候,才會觸發 fetch 函數,這樣我們的無限滾動就更加實用啦!
支持 window 以外的元素
然而,并不是只有 window 才可以滾動,擁有高度的級塊元素只要設置了 overflow: scroll 都是可以滾動的。
我們需要再修改一下代碼來讓級塊元素也支持無限滾動!
很簡單吧!只需要為該容器元素添加一個 scroll 的事件監聽器就好啦!
出處
http://scarletsky.github.io/2016/04/20/how-to-implement-infinite-scroll/
參考資料
https://developer.mozilla.org/en-US/docs/Web/API/Element/getBoundingClientRect
總結
- 上一篇: iOS开发者有价值的工具集
- 下一篇: 导出websphere内存镜像