前端開發的時候,有些列表頁面可能會有很多圖片需要加載。一次加載太多圖片,會佔用很大的帶寬,影響網頁的加載速度。
這時候我們想到一種方式,讓用戶瀏覽到什麼地方,就加載該處的圖片。
這裏寫了一個簡單的例子,大家可以去體驗一下,當然這裏考慮到的是最簡單的情況。 這裏簡單的講解一下這個例子裏面的源碼。
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")
img{
width:600px;
height:300px;
border: 2px solid #eee;
background: #ccc;
}
#lazy-img{
height: 400px;
background:#eee;
overflow: auto;
}
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 張圖片,可以包裝成一個通用的插件等等。只要大家瞭解到了原理,那麼實現折些都很簡單。 這篇文章也算是拋磚引玉,歡迎大家進行討論。