原生JS?Intersection?Observer?API實現(xiàn)懶加載
引言
前一陣子在做一個項目的時候,因為每組數(shù)據(jù)都要先通過很龐大的計算,才把計算后的結果 Render 到頁面上,但這樣就導致如果單頁查出來的數(shù)據(jù)超過大概 5 筆,就會需要等待一段有感的時間,才能看到結果出現(xiàn)在畫面上。
后來為了解決這差勁用戶體驗,就使用到的標題上說到的 Lazy Loading 來處理。簡單說就是,雖然要顯示的數(shù)據(jù)量有 10 筆,但因為一個頁面大概只能呈現(xiàn) 2 到 3 筆,那我就先計算那 2 到 3 筆數(shù)據(jù)然后顯示就好,剩下的數(shù)據(jù)等使用者往下滾再繼續(xù)顯示,這樣等待時間就不會太久。
然后身為一個前端工程師,再想到這個解法以后,當然就是上 Github 找一個簡單又方便的組件來解決它 ??,而最后找到的 vue-scroll-loader 使用起來非常容易,代碼也少少的,所以就在處理完 issue 后,看它內部是如何實現(xiàn) Lazy Loading,于是就看到今天主要講的 Intersection Observer API 啦!
Intersection Observer API
那 Intersection Observer API 到底是什麼?為什麼它可以用來實現(xiàn) Lazy Loading 呢?以 MDN 的說法來說:
Intersection Observer API 提供了一種異步檢測目標元素與祖先元素或 viewport 相交情況變化的方法。
簡單說的意思就是只要使用 Intersection Observer API,就能夠監(jiān)聽目標的元素在畫面上出現(xiàn)或離開的時候,執(zhí)行你交給它的 callback 方法。下方就來看看使用的方式吧!
使用方法
首先要有簡單的 HTML 和 CSS,主要目標就是把 div 放在往下滾才會出現(xiàn)的地方:
body { height: 1000px; } .box { width: 100px; height: 100px; background: #000; position: absolute; top: 500px; }
<body> <div class="box"></div> </body>
接著我們用 Intersection Observer API 的 observe
方法,把要監(jiān)聽的 div
當作參數(shù)傳給它,并用 callback
讓它可以在 div 出現(xiàn)和離開的時候給個消息:
const intersectionObserver = new IntersectionObserver( () => { console.log('hi'); } ); intersectionObserver.observe( document.querySelector('.box') );
執(zhí)行的結果就會像這樣子:
而 Intersection Observer API 在執(zhí)行 callback
的時候,也會給你一個 Array
,Array
是所有正在監(jiān)聽的元素,我們可以從這些元素里的 isIntersecting
來判斷當前的元素是出現(xiàn)在畫面中,還是離開畫面了:
const intersectionObserver = new IntersectionObserver( (entries) => { if (entries[0].isIntersecting) { console.log('我進來了!'); } else { console.log('我又出去了!'); } } ); intersectionObserver.observe( document.querySelector('.box') );
執(zhí)行結果:
最后就是當你不再需要繼續(xù)監(jiān)聽元素的時候,可以使用 unobserve
來解除監(jiān)聽,使用時就像監(jiān)聽用的 observe
一樣,給它不需要再監(jiān)聽的元素:
intersectionObserver.unobserve( document.querySelector('.box') );
以上就是 Intersection Observer API 的基本用法,當然還有其他比較仔細的設置(可以看 MDN 的介紹),但如果要完成一個簡單的 Lazy Loading,那只要會上方的幾種使用方式就綽綽有馀了!
Lazy Loading
Intersection Observer API 實現(xiàn) Lazy Loading 的方法就是在數(shù)據(jù)列表的最后放個 loading
的小動畫,接著只要去監(jiān)聽小動畫,當它出現(xiàn)在頁面中的時候,用 Intersection Observer API 的 callback
載入更多數(shù)據(jù)。
首先一樣先簡單寫個要顯示數(shù)據(jù)的 <ul>
,和要監(jiān)聽的元素,這裡我就不做小動畫了,直接用 Loading…
文字代替 ??:
<body> <ul class="list"></ul> <div class="loading">Loading...</div> </body>
要注意監(jiān)聽的元素必須要在載入數(shù)據(jù)的最下面哦!不然它不會被監(jiān)聽到“出現(xiàn)在頁面上”了(這個下方會更詳細說明注意事項)。
JavaScript 的部分先貼代碼,下方再來解釋:
const data = Array.from(Array(200)).map( (_value, index) => `第 ${index + 1} 筆資料` ); const render = () => { const list = document.querySelector('.list'); const LOAD_DATA_COUNT = 50; const startLoadIndex = list.childNodes.length; const endLoadIndex = startLoadIndex + LOAD_DATA_COUNT; for (let i = startLoadIndex; i < endLoadIndex; i++) { if (data[i]) { const text = document.createTextNode(data[i]); const li = document.createElement('li'); li.appendChild(text); list.appendChild(li); } } if (endLoadIndex >= data.length) { const loading = document.querySelector('.loading'); loading.style.display = 'none'; intersectionObserver.unobserve(loading); } }; render(); const intersectionObserver = new IntersectionObserver( (entries) => { if (entries[0].isIntersecting) { setTimeout(render, 1000); } } ); intersectionObserver.observe( document.querySelector('.loading') );
- 先用循環(huán)產生 200 筆的假數(shù)據(jù)
- 寫一個
render
的方法,把還沒載入的數(shù)據(jù)循環(huán)加去,這里一次加 50 筆數(shù)據(jù) - 在
render
內加完數(shù)據(jù),去判斷當前加到的index
有沒有大于數(shù)據(jù)總數(shù),如果有的話代表所有數(shù)據(jù)顯示完了,因此隱藏loading
,并移除 Intersection Observer API 對loading
的監(jiān)聽 - 畢竟一開始畫面上還是要有數(shù)據(jù)!所以先手動執(zhí)行第一次
render
方法 - 用 Intersection Observer API 監(jiān)聽
loading
,只要一出現(xiàn)在畫面上(代表使用者看完目前的數(shù)據(jù),就要在執(zhí)行render
。這裡為了有真正render
的感覺,我用setTimeout
來延遲1
秒
執(zhí)行的效果就會像這樣子:
但是還有一點要注意的地方,以上方的例子來說,如果 Intersection Observer API 因為 loading
出現(xiàn)在頁面中執(zhí)行了 render,但是 render 后的數(shù)據(jù)量卻不足以把 loading
移到畫面外,那 loading
就會一直停留在畫面中,而不是“出現(xiàn)在畫面中”,這麼一來,Intersection Observer API 也就不會觸發(fā) render
載入更多數(shù)據(jù)。
最后來看一下支持情況。ntersection Observe API 的支持度算不錯了,但如果產品有要考慮到 IE 的客戶群就沒辦法用了。 ??
最后還是覺得從開源項目里面以學到很多有趣的東西,也推薦大家可以在使用某些組件時候偷看一下背后的源碼怎麼處理的。 ??
~完,我是刷碗智,新的一年,我們一起洗刷刷新!!
代碼部署后可能存在的BUG沒法實時知道,事后為了解決這些BUG,花了大量的時間進行l(wèi)og 調試,這邊順便給大家推薦一個好用的BUG監(jiān)控工具 Fundebug。
原文:https://medium.com/starbugs/%...
以上就是原生JS Intersection Observer API實現(xiàn)懶加載的詳細內容,更多關于JS Intersection Observer API懶加載的資料請關注腳本之家其它相關文章!
相關文章
在vue項目創(chuàng)建的后初始化首次使用stylus安裝方法分享
下面小編就為大家分享一篇在vue項目創(chuàng)建的后初始化首次使用stylus安裝方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-01-01