背景
最近看到很多网站都运用到了一种前端数据延迟加载技术,包括淘宝,新浪网等等,这样做的目的可以使得一些未显示的图片随 着滚动条的滚动进行延迟显示。
好处显而易见,可以减少前端对于图片的Http请求,减轻对于服务器的压力,对于长篇并且大批量的图片的网页很有帮助。
详细分析
1. 今天就来介绍如何设计这样的一种jQuery插件。
jQuery官方也开放一个Lazyload插件,但是用了一下,发现它 有些问题,在网页加载的时候(具体地址可以参考这个Demo:http://www.appelsiini.net/projects/lazyloa d/enabled_container.html),利用HttpWatch可以发现,六张图片其实都有在下载,只是在下载过程中,他会将src路径转换 为orginal路径,当转换为orginal路径时,http请求就会被终止(Aborted),如果拉动滚动条,它会把original路径再转换为src的 路径。同时可以在HttpWatch中观察到它获取得到一个206的HttpCode,206协议是Partial Content,也就是服务端只接收到了部分Http请求。因此,在图片尺寸比较大的情况下,图片加载较慢,因此请求会被拦截,并且保留客户端数据,在下次Img标签加载Load方法的时候,可以继续请求图片数据。HttpWatch查看效果如下:
图上有3个图片的Http请求被终止。
2. 如果我想让它在网页加载的时候,只要没显示的图片,就不要让它去调用请求,那么该如何实现呢?那么开始以下我的设计。
首先,我们考虑到一个Img标签如果具有src属性,并且已经在 Html加载出来的时候,会自动去请求服务端,甚至<img src=” ” />都会去请求服务端。所以,在你加载具有src路径的图片之前,必须让它不被加载,我这里使用到的一个技巧,将包含Img 标签的DOM元素全仍进一个Textarea文本框中,这样就不会去请求路径。
jQuery插件代码:
//包装延迟加载容器
$.fn.wraplazyload = function(value) {
this.html('<textarea class="text-lazyload">' + value + '</textarea>');
};
其中将text-lazyload的display设置为none,让它不显示。
接着,我需要开始“解放”图片了
jQuery插件代码:
var content = $('<div>' + $(this).val().replace (/src=/gi, 'dynamic=') + '</div>');
$(this).after(content);
这里的this指的是刚才包装的textarea,这里首先把Html内容 的包含“src=”的文本替换为“dynamic=” (注:这里简单进行 这样的替换,如果一般性的考虑的话),
然后创建一个jQuery对象,在textarea后面追加这样的一个DOM 节点。利用dynamic的替代属性,就防止了图片的加载。
3. 该jQuery插件不尽支持对于Img图片的延迟加载,对于任何 一个DOM节点都可以进行延迟加载。
jQuery插件代码:
element.each(function() { $(this).css('visibility', 'hidden'); });
element为一系列DOM元素或者Img标签,注意这里要使用 visibility:hidden,这样才能保持DOM元素或者Img标签的高度,display:none,会将元素的高度置0.
4. 然后,开始编写滚动条触发事件代码:
jQuery插件代码:
代码 $(settings.container).bind(settings.event, function(event) { var pixel = 0;
if (settings.position == 'vertical') {
pixel = $(settings.container).height() + $(settings.container).scrollTop();
}
else if (settings.position == 'horizontal') {
pixel = $(settings.container).width() + $(settings.container).scrollLeft();
} element.each(function() {
if ($(this).css('visibility') != 'visible' &&
(settings.position == 'vertical' && pixel >= $(this).offset().top
|| settings.position == 'horizontal' && pixel >= $(this).offset().left)) { $(this).css('visibility', 'visible'); if (settings.effect == 'fadeIn') {
$(this).hide();
$(this)[settings.effect](settings.effectTime);
}
if (settings.loadType == 'item')
$(this).html($(this).html().replace(/dynamic=/gi, 'src='));
else if (settings.loadType == 'image')
$(this).attr('src', $(this).attr('dynamic')).removeAttr('dynamic');
}
});
});
当滚动条将图片或者DOM节点给展示出来的时候,会调用$(this).css('visibility', 'visible');
并且如果是加载图片,将调用$(this).attr('src', $(this).attr('dynamic')).removeAttr('dynamic');
如果是加载Dom节点,将调用$(this).html($(this).html ().replace(/dynamic=/gi, 'src='));
思路是将dynamic转换为src,得以进行Http请求。
5. 最后看代码如何应用该插件:
前端JS代码:
代码 var html = '';
html += '<div class="item-lazyload"><img src="http://img9.zol.com.cn/desk_pic/big_152/151653.jpg" width="600" height="500" /><br/><img src="http://img9.zol.com.cn/desk_pic/big_413/412107.jpg" width="600" height="500" /></div>';
html += '<div class="item-lazyload"><img src="http://img9.zol.com.cn/desk_pic/big_152/151656.jpg" width="600" height="500" /></div>';
html += '<div class="item-lazyload"><img src="http://img9.zol.com.cn/desk_pic/big_413/412108.jpg" width="600" height="500" /></div>';
html += '<div class="item-lazyload"><img src="http://img9.zol.com.cn/desk_pic/big_419/418139.jpg" width="600" height="500" /></div>';
html += '<div class="item-lazyload"><img src="http://img9.zol.com.cn/desk_pic/big_152/151647.jpg" width="600" height="500" /></div>';
$('#container2').wraplazyload(html);
$('#container2').datalazyload({ loadType: 'image', effect: 'fadeIn'/*, position: 'horizontal'*/ });
Html代码:
<div id="container2">
</div>
首先对于container2节点进行包装,然后调用datalazyload方 法,这里loadType加载类型为加载图片“image”,也可以设置为 加载DOM节点“item”,effect为加载效果,position可以设置为 水平加载还是垂直加载,Options参数完整为:
jQuery插件代码:
代码 var settings = {
dataContainer: '.text-lazyload',
dataItem: '.item-lazyload',
loadType: 'item', //可以为item(条目加载),img(图片加载)
container: window, //滚动的容器
event: 'scroll',
effect: 'normal', //效果类型
effectTime: 1000, //效果持续时间
position: 'vertical' //可以为vertical(垂直加载),horizontal(水平加载)
};
这些参数都是可设置的,这里不在过多介绍,具体可以查看源代码。
6. 最后,插件只有在滚动条拉到DOM节点或者图片的可视区域的时候,才进行加载,达到了数据延迟加载的效果。该插件已经成功应用到项目中去了.
数据延迟加载JQuery插件的演示地址:http://aspspider.info/sunleepy/lazyload.html