原生實現img-lazyLoad:圖片延遲加載(基於intersection Observer)

intersection Observer簡介

點擊查閱MDN關於此api的使用說明

這個api是用來檢測dom元素交集的,常見的應用場景之一就是本文提到的對圖片進行懶加載,即:拖動窗口滾動條,到達當前這個圖片的時候,再去讀取掛在自定義屬性(比如:'data-src')上的url地址,之後將該url地址寫到到src屬性上去進行下載、展示這個圖片。因此,我們關注的重點是:該圖片是否滾動到了當前窗口的可視區域。通常解決的辦法是,監聽窗口元素的scroll事件,在事件處理程序中對圖片的位置做判斷。然而,這麼做的一個弊端是,因爲js是單線程的,而scroll事件出現的又很密集,每次都去響應scroll事件可能會影響用戶體驗。

intersection Observer的誕生就是爲了處理這種類似於上文提到的元素交集檢測。它會觀察我們的目標元素,當目標元素出現在root元素的可視區域時便會觸發一個(我們事先放進去的)回調函數,於是我們可以在回調函數裏面處理業務邏輯。

這裏出現了兩個小概念,對應於本文實現的圖片懶加載功能來說:

  • 目標元素:指的就是那些我們需要懶加載的圖片
  • root元素指的就是目標元素的父窗口,比如這裏的圖片的父元素容器

利用intersection Observer實現懶加載

點此查看該案例的stackblitz

查看該案例:

  1. 在index.html頁面內有一個scrollContainer,在裏面首先是放了幾段文字,之後是5個img元素,並將img的url地址寫在了自定義屬性'data-src'內。
  2. 在css文件內定義了一些樣式,其中,move-in是在我們對圖片真正進行加載時纔會添加的動畫效果。

現在,無論我們怎麼拖動滾動條都無法看見圖片,因爲我們僅僅是把img的url寫在了自定義屬性中而不是src屬性中。接下來,我們需要利用intersection Observer對這些暫時看不見的圖片元素進行觀察,當確認他們滾動到了窗體的可視區域時,我們在回調函數中對其進行加載。

創建一個observer:

const observer = new IntersectionObserver(callback,option)

option配置root元素和回調函數觸發機制,這裏我們將scrollContainer這個div設爲root。
callback就是當檢測到目標元素與root元素交集時會調用的函數,形如:

(entrances, observer)=>{
    // entrances是個數組對象,包含了所有的目標元素,通常我們會遍歷它們,並判斷每一個單獨的個體是否與root元素產生了交集,如果是,那麼我們就會執行一些邏輯
}

連接目標元素

剛纔我們創建了observer,並且設置了它的root元素,現在需要告訴這個observer,我們需要觀察哪些目標元素與此root元素的交集。
通過observer.observe(target)進行鏈接

最終的代碼

const imgs = document.querySelectorAll('img') //獲取所有待觀察的目標元素
var options = {
  root: document.querySelector('.scrollContainer'), 
  rootMargin: '0px',
  threshold: 1.0
}
function lazyLoad(target) {
  const observer = new IntersectionObserver((entrances, observer) => {
    entrances.forEach(entrance => {
      if (entrance.isIntersecting) {
        const img = entrance.target;
        const src = img.getAttribute('data-src');
        img.setAttribute('src', src)
        img.classList.add('move-in')
        observer.disconnect()
      }

    })
  }, options);
  observer.observe(target)
}

imgs.forEach(lazyLoad) 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章