Webページの表示を高速化するために、ページロード初期時には画像は読み込まず、表示できるデータが存在するようになってから表示することをLazyLoad(遅延読み込み)と言います。今回は、Intersection Observerを使って、LazyLoadを作る方法について紹介したいと思います。

Intersection Observerとは

このIntersection Observerは、比較的新しいAPIで、「Intersection(要素間交差)」を「Observe(監視)」するためのAPIです。 任意の要素(DOM)同士の交差を監視することが出来ます。デフォルトでviewport(見えている範囲)とある要素が交差=ある要素が見えたら何かする、というものです。詳しくは、こちらを参照して下さい。

サンプルコード

image_containerというidが割り振られたdiv要素の中に複数の画像要素があるケースでは、下記のような形で利用します。

      const load = () => {
        const loadImage = (target) => {
          target.addEventListener("load", () => {
            setTimeout(() => el.classList.add("loaded"), 500);
          })
          target.addEventListener("error", () => {
            console.log("error")
          })
          target.src = target.dataset.url
        }
        const el = document.getElementById("image_container")
        const observer = new IntersectionObserver((entries, observer) => {
          entries.forEach(function(entry) {
            if (entry.isIntersecting) {
              const images = el.querySelectorAll('img')
              console.log(images)
              images.forEach((imgEl) => {
                loadImage(imgEl)
              })
              observer.unobserve(el)
            }
          })
        })
        observer.observe(el)
      }
      window.addEventListener('load', load)

JSの処理についてざっくり話すと、遅延読み込みしたい要素をIntersection Observerで監視するよう設定しています。この要素の子要素には、複数のimgタグがある想定です。
ビューポートに少しでも要素が交差したら、data-url属性に指定している画像をロードするという処理になっています。

Vue/Nuxtでこれを実装する場合は、ディレクティブのinsertedと組み合わせて、上記処理を行うようにするとLazyLoadするimgコンポーネントが実装できます。

昔は、scrollイベントとなどと組み合わせてlazyload機能を実装するなどして、あまり独自に実装するということがなかったかもしれませんが、Intersection Observerを利用することでシンプルに実装ができます。お疲れさまでした。