延遲加載也稱爲惰性加載,即在長網頁中延遲加載圖像。用戶滾動到它們以前,視口外的圖像不會加載。這與圖像預加載相反,在長網頁上使用延遲加載將使網頁加載更快。在某些狀況下,它還能夠幫助減小服務器負載。javascript
那麼延遲加載有什麼好處:
一、提高用戶的體驗,避免出現卡頓現象。
二、有選擇性地請求圖片,減小服務器的壓力和流量,減少瀏覽器的負擔。css
實現方式:
一、首先將頁面上的圖片的 src 屬性設爲 loading.gif,而圖片的真實路徑則設置在 data-src 屬性中,頁面滾動的時候計算圖片的位置與滾動的位置,當圖片出如今瀏覽器視口內時,將圖片的 src 屬性設置爲 data-src 的值,這樣,就能夠實現延遲加載html
<!DOCTYPE html> <html > <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 的大小,當小於時則說明圖片已經出現過在視口中,這時候繼續判斷圖片是否已經替換過,若是沒有替換過,則進行替換。java
上面的代碼是沒什麼問題,可是性能誤差。若是直接將函數綁定在 scroll 事件上,當頁面滾動時,函數會被高頻觸發,這很是影響瀏覽器的性能。我粗略地估計一下,當簡單地滾動一下頁面,函數至少觸發了十來次,這顯然是十分不必的。瀏覽器
二、因此在作事件綁定的時候,能夠對 lazyload 函數進行函數節流(throttle)與函數去抖(debounce)處理。緩存
Debounce:一部電梯停在某一個樓層,當有一我的進來後,20秒後自動關門,這20秒的等待期間,又一我的按了電梯進來,這20秒又從新計算,直到電梯關門那一刻纔算是響應了事件。
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 執行該函數。app
預加載圖片是提升用戶體驗的一個很好方法。圖片預先加載到瀏覽器中,訪問者即可順利地在你的網站上衝浪,並享受到極快的加載速度。這對圖片畫廊及圖片佔據很大比例的網站來講十分有利,它保證了圖片快速、無縫地發佈,也可幫助用戶在瀏覽你網站內容時得到更好的用戶體驗。ide
一、用CSS和JavaScript實現預加載函數
#preload-01 { background: url(-01.png) no-repeat -9999px -9999px; } #preload-02 { background: url(-02.png) no-repeat -9999px -9999px; } #preload-03 { background: url(-03.png) no-repeat -9999px -9999px; }
將這三個ID選擇器應用到(X)HTML元素中,咱們即可經過CSS的background屬性將圖片預加載到屏幕外的背景上。只要這些圖片的路徑保持不變,當它們在Web頁面的其餘地方被調用時,瀏覽器就會在渲染過程當中使用預加載(緩存)的圖片。簡單、高效,不須要任何JavaScript。
該方法雖然高效,但仍有改進餘地。使用該法加載的圖片會同頁面的其餘內容一塊兒加載,增長了頁面的總體加載時間。爲了解決這個問題,咱們增長了一些JavaScript代碼,來推遲預加載的時間,直到頁面加載完畢。代碼以下:
function preloader() { if (document.getElementById) { document.getElementById("preload-01").style.background = "url() no-repeat -9999px -9999px"; document.getElementById("preload-02").style.background = "url() no-repeat -9999px -9999px"; document.getElementById("preload-03").style.background = "url() no-repeat -9999px -9999px"; } } function addLoadEvent(func) { var oldonload = window.onload; //得到window.onload的內容 if (typeof window.onload != 'function') { //判斷windown.onload是否爲函數。若是不是函數,則執行本身的函數,若是是函數,則先執行已經賦值的函數,再執行本身的函數 window.onload = func; } else { window.onload = function() { if (oldonload) { oldonload(); } func(); } } } addLoadEvent(preloader);
二、純JavaScript實現,與Css實現相比,會減小時間
function preloader() { if (document.images) { var img1 = new Image(); var img2 = new Image(); var img3 = new Image(); img1.src = ";; img2.src = ";; img3.src = ";; } } function addLoadEvent(func) { var oldonload = window.onload; if (typeof window.onload != 'function') { window.onload = func; } else { window.onload = function() { if (oldonload) { oldonload(); } func(); } } } addLoadEvent(preloader);
三、使用Ajax實現預加載
上面所給出的方法彷佛不夠酷,那如今來看一個使用Ajax實現圖片預加載的方法。該方法利用DOM,不只僅預加載圖片,還會預加載CSS、JavaScript等相關的東西。使用Ajax,比直接使用JavaScript,優越之處在於JavaScript和CSS的加載不會影響到當前頁面。該方法簡潔、高效。
window.onload = function() { setTimeout(function() { // XHR to request a JS and a CSS var xhr = new XMLHttpRequest(); xhr.open('GET', ';); xhr.send(''); xhr = new XMLHttpRequest(); xhr.open('GET', ';); xhr.send(''); // preload image new Image().src = ";; }, 1000); };
上面代碼預加載了「preload.js」、「preload.css」和「preload.png」。1000毫秒的超時是爲了防止腳本掛起,而致使正常頁面出現功能問題。
window.onload = function() { setTimeout(function() { // reference to <head> var head = document.getElementsByTagName('head')[0]; // a new CSS var css = document.createElement('link'); css.type = "text/css"; css.rel = "stylesheet"; css.href = ";; // a new JS var js = document.createElement("script"); js.type = "text/javascript"; js.src = ";; // preload JS and CSS head.appendChild(css); head.appendChild(js); // preload image new Image().src = ";; }, 1000); };