iT邦幫忙

0

[JS]透過IntersectionObserver達成個別/全頁圖片lazy load

當撰寫顯示多個(例如:展示數百筆廣告)圖片的網頁時,效能與用戶體驗主要有以下課題:

  1. 如何節省不必要的加載(不加載使用者還沒看到的)
  2. 批次載入圖片(每次載入100筆,看完再加載另外100筆)

例如公司開發了一隻產品,其功能讓使用者選擇多個品牌(例:肯德基,家樂福...),按下搜尋後顯示我們從資料查詢到這些廠商的廣告圖片,少則數十,多則數千。

這時如果我們可以每次載入100筆,並且只在使用者"將要"看到某張圖片時或者某張圖片"已經"出現在使用者的畫面上,才向server請求該圖片,如此一來便可以大幅提升網頁渲染的速度,同時節省client與server的負擔,關於這一點,可以請大家一同觀賞這篇好文。

好文共賞

基於上文範例,我們可以進一步思考,是不是可以利用IntersectionObserver的特性,達到我們的第2個目標:在使用者看完目前的圖片時,載入後續的圖片

因此解決方法的關鍵點在於當IntersectionObserver監聽到目前最後一筆圖片出現在螢幕上時,除了要向server請求這張圖片外,還要向server請求並渲染後續的圖片

為了達到這樣的目標,我們可以設定每次載入100筆圖片,並在生成每張圖片時為它添加data-id屬性,值為它出現的順序(1,2,3,...),如此一來當IntersectionObserver監聽圖片的data-id值若為100的倍數,請求這張圖片同時調用請求後續圖片的函式。

this._observer = new IntersectionObserver((entries, observer) => {
      const ins = this;

      entries.forEach(e=>{
          if(e.isIntersecting){
            const container = e.target;
            //圖片載入顯示時加一點特效
            container.classList.add("fadeIn");
            const img = container.querySelector("img");
            img.setAttribute("src", img.dataset.url);
            img.removeAttribute("data-url");
            observer.unobserve(container);
  
            //當圖片的data-id值為100的倍數時,呼叫向伺服器請求並渲染圖片的方法
            //第二個條件可以選用,讓你控制每頁圖片的最大數量
            if (container.dataset.id % 100 === 0 && container.dataset.id <= 400) {
              ins.generateImg(100);
            }
          }
      });
    });

如此一來便可以達到我們設定的兩個目標,只載入使用者螢幕上的圖片以及批次載入圖片,而這一切都可以靠運用IntersectionObserver達成,以下是我在codePen上對該方法的實踐,提供大家參考。

點我看示範


圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言