定義:延遲加載也稱爲惰性加載,即在長網頁中延遲加載圖像。用戶滾動到它們以前,視口外的圖像不會加載。這與圖像預加載相反,在長網頁上使用延遲加載將使網頁加載更快。在某些狀況下,它還能夠幫助減小服務器負載。html
舉個例子來講明,當打開淘寶首頁的時候,只有在瀏覽器窗口裏的圖片纔會被加載,當你滾動首頁向下滑的時候,進入視口內的圖片纔會被加載,而其它從未進入視口的圖像不會也不會加載。api
那麼延遲加載有什麼好處:數組
那麼下面就介紹延遲加載的三種實現方式:瀏覽器
第一種:服務器
首先將頁面上的圖片的 src 屬性設爲 loading.gif,而圖片的真實路徑則設置在 data-src 屬性中,頁面滾動的時候計算圖片的位置與滾動的位置,當圖片出如今瀏覽器視口內時,將圖片的 src 屬性設置爲 data-src 的值,這樣,就能夠實現延遲加載。閉包
下面是具體的實現代碼:函數
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Lazyload 1</title> <style> img { display: block; margin-bottom: 50px; height: 200px; } </style> </head> <body> <img src="images/loading.gif" data-src="images/1.png"> <img src="images/loading.gif" data-src="images/2.png"> <img src="images/loading.gif" data-src="images/3.png"> <img src="images/loading.gif" data-src="images/4.png"> <img src="images/loading.gif" data-src="images/5.png"> <img src="images/loading.gif" data-src="images/6.png"> <img src="images/loading.gif" data-src="images/7.png"> <img src="images/loading.gif" data-src="images/8.png"> <img src="images/loading.gif" data-src="images/9.png"> <img src="images/loading.gif" data-src="images/10.png"> <img src="images/loading.gif" data-src="images/11.png"> <img src="images/loading.gif" data-src="images/12.png"> <script> function lazyload() { var images = document.getElementsByTagName('img'); var len = images.length; var n = 0; //存儲圖片加載到的位置,避免每次都從第一張圖片開始遍歷 return function() { var seeHeight = document.documentElement.clientHeight; var scrollTop = document.documentElement.scrollTop || document.body.scrollTop; for(var i = n; i < len; i++) { if(images[i].offsetTop < seeHeight + scrollTop) { if(images[i].getAttribute('src') === 'images/loading.gif') { images[i].src = images[i].getAttribute('data-src'); } n = n + 1; } } } } var loadImages = lazyload(); loadImages(); //初始化首頁的頁面圖片 window.addEventListener('scroll', loadImages, false); </script> </body> </html>
比較 image 的 offsetTop 與 seeHeight + scrollTop 的大小,當小於時則說明圖片已經出現過在視口中,這時候繼續判斷圖片是否已經替換過,若是沒有替換過,則進行替換。性能
實現的效果:不斷滑動頁面時,圖片延遲加載code
你能夠拷貝個人代碼去進行實驗,可是請確保 HTML 同目錄下有 images 目錄而且含有 1~12.png 和 loading.gif。server
須要說起的是變量 n 是用來保存已經加載的圖片數量,避免每次都從第一張圖片開始遍歷,提高性能。上面的代碼用到了 JS 閉包的知識,若是你不太熟悉的話,能夠自行百度一下。
第二種:
上面的代碼是沒什麼問題,可是性能誤差。若是直接將函數綁定在 scroll 事件上,當頁面滾動時,函數會被高頻觸發,這很是影響瀏覽器的性能。我粗略地估計一下,當簡單地滾動一下頁面,函數至少觸發了十來次,這顯然是十分不必的。
因此在作事件綁定的時候,能夠對 lazyload 函數進行函數節流(throttle)與函數去抖(debounce)處理。
這裏我並再也不另外介紹這兩種方案,若是你想了解的話能夠閱讀:JS魔法堂:函數節流(throttle)與函數去抖(debounce) - ^_^肥仔John - 博客園
簡單說來:
下面就是通過 throttle 處理後的代碼:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Lazyload 2</title> <style> img { display: block; margin-bottom: 50px; height: 200px; } </style> </head> <body> <img src="images/loading.gif" data-src="images/1.png"> <img src="images/loading.gif" data-src="images/2.png"> <img src="images/loading.gif" data-src="images/3.png"> <img src="images/loading.gif" data-src="images/4.png"> <img src="images/loading.gif" data-src="images/5.png"> <img src="images/loading.gif" data-src="images/6.png"> <img src="images/loading.gif" data-src="images/7.png"> <img src="images/loading.gif" data-src="images/8.png"> <img src="images/loading.gif" data-src="images/9.png"> <img src="images/loading.gif" data-src="images/10.png"> <img src="images/loading.gif" data-src="images/11.png"> <img src="images/loading.gif" data-src="images/12.png"> <script> function throttle(fn, delay, atleast) { var timeout = null, startTime = new Date(); return function() { var curTime = new Date(); clearTimeout(timeout); if(curTime - startTime >= atleast) { fn(); startTime = curTime; }else { timeout = setTimeout(fn, delay); } } } function lazyload() { var images = document.getElementsByTagName('img'); var len = images.length; var n = 0; //存儲圖片加載到的位置,避免每次都從第一張圖片開始遍歷 return function() { var seeHeight = document.documentElement.clientHeight; var scrollTop = document.documentElement.scrollTop || document.body.scrollTop; for(var i = n; i < len; i++) { if(images[i].offsetTop < seeHeight + scrollTop) { if(images[i].getAttribute('src') === 'images/loading.gif') { images[i].src = images[i].getAttribute('data-src'); } n = n + 1; } } } } var loadImages = lazyload(); loadImages(); //初始化首頁的頁面圖片 window.addEventListener('scroll', throttle(loadImages, 500, 1000), false); </script> </body> </html>
設置了 500ms 的延遲,和 1000ms 的間隔,當超過 1000ms 未觸發該函數,則當即執行該函數,否則則延遲 500ms 執行該函數。
實現效果:能夠看出有必定的延遲。
參考連接:實現圖片懶加載(lazyload)
第三種: 使用 IntersectionObserver API
目前有一個新的 IntersectionObserver API,能夠自動"觀察"元素是否可見,Chrome 51+ 已經支持。
這裏不過多介紹 IntersectionObserver API 的詳細使用,感興趣能夠另外閱讀下面的文章:
IntersectionObserver API 使用教程
Intersection Observer API
實現代碼:簡潔,可是瀏覽器還沒有所有實現。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Lazyload 3</title> <style> img { display: block; margin-bottom: 50px; width: 800px; } </style> </head> <body> <img src="images/loading.gif" data-src="images/1.png"> <img src="images/loading.gif" data-src="images/2.png"> <img src="images/loading.gif" data-src="images/3.png"> <img src="images/loading.gif" data-src="images/4.png"> <img src="images/loading.gif" data-src="images/5.png"> <img src="images/loading.gif" data-src="images/6.png"> <img src="images/loading.gif" data-src="images/7.png"> <img src="images/loading.gif" data-src="images/8.png"> <img src="images/loading.gif" data-src="images/9.png"> <img src="images/loading.gif" data-src="images/10.png"> <img src="images/loading.gif" data-src="images/11.png"> <img src="images/loading.gif" data-src="images/12.png"> <script> function query(selector) { return Array.from(document.querySelectorAll(selector)); } var io = new IntersectionObserver(function(items) { items.forEach(function(item) { var target = item.target; if(target.getAttribute('src') == 'images/loading.gif') { target.src = target.getAttribute('data-src'); } }) }); query('img').forEach(function(item) { io.observe(item); }); </script> </body> </html>
實現效果: