背景
最近看到很多网站都运用到了一种前端数据延迟加载技术,包括淘宝,新浪网等等,这样做的目的可以使得一些未显示的图片随 着滚动条的滚动进行延迟显示。
好处显而易见,可以减少前端对于图片的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
源代码下载