前端性能優化之 —— 圖片延遲加載 (原理以及實現方式)

前端開發的時候,有些列表頁面可能會有很多圖片需要加載。一次加載太多圖片,會佔用很大的帶寬,影響網頁的加載速度。

這時候我們想到一種方式,讓用戶瀏覽到什麼地方,就加載該處的圖片。

這裏寫了一個簡單的例子,大家可以去體驗一下,當然這裏考慮到的是最簡單的情況。 這裏簡單的講解一下這個例子裏面的源碼。

例子查看

DOM 結構

由一個父容器div#lazy-img,裏面是圖片標籤,父容器是可以滾動的,圖片有固定高度。大家可以看到,容器內的img元素沒有 src 屬性,而有一個 data-src 屬性。 這是不想讓圖片提前加載,所以把圖片的鏈接儲存到data-src 內。

div#lazy-img
  img(data-src="https://file.diamondfsd.com/img/9c61bc16-ae02-4f06-a8aa-0501db51eadb.png")
  img(data-src="https://file.diamondfsd.com/img/9c61bc16-ae02-4f06-a8aa-0501db51eadb.png")
  img(data-src="https://file.diamondfsd.com/img/9c61bc16-ae02-4f06-a8aa-0501db51eadb.png")
  img(data-src="https://file.diamondfsd.com/img/9c61bc16-ae02-4f06-a8aa-0501db51eadb.png")
  img(data-src="https://file.diamondfsd.com/img/9c61bc16-ae02-4f06-a8aa-0501db51eadb.png")
  img(data-src="https://file.diamondfsd.com/img/9c61bc16-ae02-4f06-a8aa-0501db51eadb.png")
  img(data-src="https://file.diamondfsd.com/img/9c61bc16-ae02-4f06-a8aa-0501db51eadb.png")
  img(data-src="https://file.diamondfsd.com/img/9c61bc16-ae02-4f06-a8aa-0501db51eadb.png")
  img(data-src="https://file.diamondfsd.com/img/9c61bc16-ae02-4f06-a8aa-0501db51eadb.png")
Pug
img{
  width:600px;
  height:300px;
  border: 2px solid #eee;
  background: #ccc;
}
#lazy-img{
  height: 400px;
  background:#eee;
  overflow: auto;
}
CSS

Javascript 代碼

我們獲取容器內所有有 data-src 屬性的dom對象,遍歷獲取他們的相對高度,儲存成 { height: imgDom} 格式。然後監聽 容器的滾動事件,當滾動的時候,計算當前滾動區域顯示的圖片dom,並將改 圖片dom 的 src 的內容改成我們存儲在 data-src 的內容。

var imgContainer = document.getElementById('lazy-img')
var imgs = imgContainer.querySelectorAll('[data-src]')
var imgHeightDomMapping = {}
imgs.forEach(function (img) {
  imgHeightDomMapping[img.offsetTop + img.clientHeight / 1.5] = img
})  // 獲取所有 dom 對象相對容器的高度 並儲存成 key: height, value: imgDom

imgContainer.addEventListener('scroll', function () {
  showImage()
})

function showImage () {
  var currentHeight = imgContainer.clientHeight + imgContainer.scrollTop // 滾動區域的高度
  Object.keys(imgHeightDomMapping).forEach(function (imageHeight) {
    if (currentHeight > imageHeight) { // 判斷當前圖片是否已經顯示
        //將圖片dom的 `src` 改爲 `data-src` 的內容
        imgHeightDomMapping[imageHeight].src = imgHeightDomMapping[imageHeight].getAttribute('data-src')
    }
  })
}

showImage() // 主動調用一次 加載首頁的

這裏簡單的實現了一個延遲加載,主要是告訴大家原理,可擴展的地方還很多。 例如提前加載 N 張圖片,可以包裝成一個通用的插件等等。只要大家瞭解到了原理,那麼實現折些都很簡單。 這篇文章也算是拋磚引玉,歡迎大家進行討論。

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