一、为何要使用懒加载?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
}
}