實現圖片懶加載的幾種方案比較

懶加載,顧名思義,在當前網頁,滑動頁面到能看到圖片的時候再加載圖片javascript

故問題拆分紅兩個:html

  1. 如何判斷圖片出如今了當前視口 (即如何判斷咱們可以看到圖片)
  2. 如何控制圖片的加載

本篇文章原文地址: 如何實現圖片懶加載,另存到 個人每日一題,歡迎 starjava

方案一

如何判斷圖片出如今了當前視口

clientTopoffsetTopclientHeight 以及 scrollTop 各類關於圖片的高度做比對git

這些高度都表明了什麼意思?程序員

這我之前有多是知道的,那時候我比較單純,喜歡死磕。我如今想通了,背不過的東西就不要背了github

因此它有一個問題:複雜瑣碎很差理解!web

僅僅知道它靜態的高度還不夠,咱們還須要知道動態的面試

如何動態?監聽 window.scroll 事件後端

如何控制圖片的加載

<img data-src="shanyue.jpg">
複製代碼

首先設置一個臨時屬性 data-src,控制加載時使用 src 代替 data-src瀏覽器

方案二

改進一下

如何判斷圖片出如今了當前視口

引入一個新的 API, Element.getBoundingClientRect() 方法返回元素的大小及其相對於視口的位置。

getBoundingClientRect示例圖

那如何判斷圖片出如今了當前視口呢,根據示例圖示意,代碼以下,這個就比較好理解了,就能夠很容易地背會(就能夠愉快地去面試了)。

// clientHeight 表明當前視口的高度
img.getBoundingClientRect().top < document.documentElement.clientHeight
複製代碼

監聽 window.scroll 事件也優化一下

加個節流器,提升性能。工做中通常使用 lodash.throttle 就能夠了,萬能的 lodash 啊!

_.throttle(func, [wait=0], [options={}])
複製代碼

參考 什麼是防抖和節流,他們的應用場景有哪些

方案三

再改進一下

如何判斷圖片出如今了當前視口

方案二使用的方法是: window.scroll 監聽 Element.getBoundingClientRect() 並使用 _.throttle 節流

一系列組合動做太複雜了,因而瀏覽器出了一個三合一事件: IntersectionObserver API,一個可以監聽元素是否到了當前視口的事件,一步到位!

事件回調的參數是 IntersectionObserverEntry 的集合,表明關因而否在可見視口的一系列值

其中,entry.isIntersecting 表明目標元素可見

const observer = new IntersectionObserver((changes) => {
  // changes: 目標元素集合
  changes.forEach((change) => {
    // intersectionRatio
    if (change.isIntersecting) {
      const img = change.target
      img.src = img.dataset.src
      observer.unobserve(img)
    }
  })
})

observer.observe(img)
複製代碼

固然,IntersectionObserver 除了給圖片作懶加載外,還能夠對單頁應用資源作預加載。

如在 next.js v9 中,會對視口內的資源作預加載,能夠參考 next 9 production optimizations

<Link href="/about">
  <a>關於山月</a>
</Link>
複製代碼

方案四

瀏覽器以爲懶加載這事能夠交給本身作,大家開發者加個屬性就行了。實在是...!

<img src="shanyue.jpg" loading="lazy">
複製代碼

不過目前瀏覽器兼容性不太好,關於 loading 屬性的文章也能夠查看 Native image lazy-loading for the web!

總結

總結一下

  • window.scroll 監聽各類 topheight 並使用 _.throttle 節流,可是很差理解各類 tophegith
  • window.scroll 監聽 getBoundingClientRect 並使用 _.throttle 節流,沒有一個統一事件,相對複雜
  • IntersectionObserver,瀏覽器推出了一個事件,方便簡單
  • img.loading=lazy,瀏覽器直接給你解決,開發者直接標註屬性

更多問題


我是山月,一個喜歡跑步與登山的程序員,我會按期分享全棧文章在我的公衆號中,歡迎交流

歡迎關注公衆號山月行,我會按期分享一些先後端以及運維的文章
相關文章
相關標籤/搜索