延遲載入(Lazyload)三種實現方式

定義:延遲載入也稱為惰性載入,即在長網頁中延遲載入影象。使用者滾動到它們之前,視口外的影象不會載入。這與影象預載入相反,在長網頁上使用延遲載入將使網頁載入更快。在某些情況下,它還可以幫助減少伺服器負載。

舉個例子來說明,當開啟淘寶首頁的時候,只有在瀏覽器窗口裡的圖片才會被載入,當你滾動首頁向下滑的時候,進入視口內的圖片才會被載入,而其它從未進入視口的影象不會也不會載入。

那麼延遲載入有什麼好處:

【1】首先它能提升使用者的體驗,試想一下,如果開啟頁面的時候就將頁面上所有的圖片全部獲取載入,如果圖片數量較大,對於使用者來說簡直就是災難,會出現卡頓現象,影響使用者體驗。

【2】有選擇性地請求圖片,這樣能明顯減少了伺服器的壓力和流量,也能夠減小瀏覽器的負擔。

那麼下面就介紹延遲載入的三種實現方式:

第一種

首先將頁面上的圖片的 src 屬性設為 loading。gif,而圖片的真實路徑則設定在 data-src 屬性中,頁面滾動的時候計算圖片的位置與滾動的位置,當圖片出現在瀏覽器視口內時,將圖片的 src 屬性設定為 data-src 的值,這樣,就可以實現延遲載入。

下面是具體的實現程式碼:

延遲載入(Lazyload)三種實現方式

比較 image 的 offsetTop 與 seeHeight + scrollTop 的大小,當小於時則說明圖片已經出現過在視口中,這時候繼續判斷圖片是否已經替換過,如果沒有替換過,則進行替換。

實現的效果:不斷滑動頁面時,圖片延遲載入

延遲載入(Lazyload)三種實現方式

需要提及的是變數 n 是用來儲存已經載入的圖片數量,避免每次都從第一張圖片開始遍歷,提升效能。

第二種

上面的程式碼是沒什麼問題,但是效能偏差。如果直接將函式繫結在 scroll 事件上,當頁面滾動時,函式會被高頻觸發,這非常影響瀏覽器的效能。我粗略地估計一下,當簡單地滾動一下頁面,函式至少觸發了十來次,這顯然是十分沒必要的。

所以在做事件繫結的時候,可以對 lazyload 函式進行函式節流(throttle)與函式去抖(debounce)處理。

簡單說來:

【1】Debounce:一部電梯停在某一個樓層,當有一個人進來後,20秒後自動關門,這20秒的等待期間,又一個人按了電梯進來,這20秒又重新計算,直到電梯關門那一刻才算是響應了事件。

【2】Throttle:好比一臺自動的飲料機,按拿鐵按鈕,在出飲料的過程中,不管按多少這個按鈕,都不會連續出飲料,中間按鈕的響應會被忽略,必須要等這一杯的容量全部出完之後,再按拿鐵按鈕才會出下一杯。

下面就是經過 throttle 處理後的程式碼:

延遲載入(Lazyload)三種實現方式

設定了 500ms 的延遲,和 1000ms 的間隔,當超過 1000ms 未觸發該函式,則立即執行該函式,不然則延遲 500ms 執行該函式。

實現效果:可以看出有一定的延遲。

延遲載入(Lazyload)三種實現方式

第三種: 使用 IntersectionObserver API

實現程式碼:簡潔,但是瀏覽器尚未全部實現。

延遲載入(Lazyload)三種實現方式

IntersectionObserve

r 傳入一個回撥函式,當其觀察到元素集合出現時候,則會執行該函式。

io.observe

即要觀察的元素,要一個個新增才可以。

io

管理的是一個數組,當元素出現或消失的時候,陣列新增或刪除該元素,並且執行該回調函式。

實現效果:

延遲載入(Lazyload)三種實現方式