一、爲何要使用懶加載?node
對於圖片過多的頁面,爲了加速頁面加載速度, 因此不少時候咱們須要將頁面內未出如今可視區域內的圖片先不作加載, 等到滾動到可視區域後再去加載。 這樣子對於頁面加載性能上會有很大的提高,也提升了用戶體驗。數組
二、如何實現?瀏覽器
其實從原理上看很簡單,在頁面載入的時候將頁面上的img標籤的src指向一個小圖片, 把真實地址存放在一個自定義屬性中,這裏我用data-src來存放,以下。網絡
<img src="loading.gif" data-src="http://xxx.ooo.com"/>
而後經過選擇器獲取頁面img標籤並保存,開啓一個定時器,遍歷保存的img標籤, 判斷其位置是否出如今了可視區域內。若是出如今可視區域了那麼就把真實的src地址給賦值上。 而且從數組中刪除,避免重複判斷。 那麼你可能會問,如何判斷是否出如今可視區域內嗎? 那就是你能夠獲取當前img的相對於文檔頂的偏移距離減去scrollTop的距離, 而後和瀏覽器窗口高度在進行比較,若是小於瀏覽器窗口則出如今了可視區域內了, 反之,則沒有。
性能
三、好的,廢話很少說,上代碼spa
window.Echo = (function (window, document, undefined) {
'use strict';
var store = [], offset, throttle, poll;code
var _inView = function (el) {//計算是否出如今視區
var coords = el.getBoundingClientRect();
return ((coords.top >= 0 && coords.left >= 0 && coords.top) <= (window.innerHeight || document.documentElement.clientHeight) + parseInt(offset));
};
var _isDeal = function(el){//是否處理過
return el.getAttribute('src') === el.getAttribute('data-src');
}
var _pollImages = function () {
for (var i = store.length; i--;) {
var self = store[i];
if (!_isDeal(self) && _inView(self)) {
self.src = self.getAttribute('data-src');
store.splice(i, 1);
}
}
};對象
var _throttle = function () {
clearTimeout(poll);
poll = setTimeout(_pollImages, throttle);
};blog
var init = function (obj) {
var nodes = document.querySelectorAll('[data-src]');
var opts = obj || {};
offset = opts.offset || 0;
throttle = opts.throttle || 250;
for (var i = 0; i < nodes.length; i++) {
store.push(nodes[i]);
}
_throttle();
if (document.addEventListener) {
window.addEventListener('scroll', _throttle, false);
} else {
window.attachEvent('onscroll', _throttle);
}
};圖片
return {
init: init,
render: _throttle
};
})(window, document);
因爲移動端網絡存在帶寬問題,使用過程當中請求的返回的數據每每作了分頁,也就是說從新請求下來的img src 並不會保存在原有的store數組當中。
getBoundingClientRect() ,這個方法返回一個矩形對象,包含四個屬性:left、top、right和bottom。分別表示元素各邊與頁面上邊和左邊的距離
拓展
上面涉及到一個計算是否在視區的方法:
注意:IE、Firefox3+、Opera9.五、Chrome、Safari支持,在IE中,默認座標從(2,2)開始計算,致使最終距離比其餘瀏覽器多出兩個像素,咱們須要作個兼容。
即:document.documentElement.clientTop; // 非IE爲0,IE爲2
document.documentElement.clientLeft; // 非IE爲0,IE爲2
functiong getRect (element) {
var rect = element.getBoundingClientRect();
var top = document.documentElement.clientTop;
var left= document.documentElement.clientLeft;
return{
top : rect.top - top,
bottom : rect.bottom - top,
left : rect.left - left,
right : rect.right - left
}
}