利用图片延迟加载来优化页面性能(jQuery)
图片延迟加载也称懒加载,常用于页面很长,图片很多的页面,以电子商务网站居多,比如大家常上的京东,淘宝,页面以图居多,整个页面少说几百K,多则上兆,如果想一次性加载完成,不仅用户要哭了,服务器也得哭了。
为了避免这种请况发生,目前主流的做法是页面初次加载时,只显示当前可视区域的图片,当用户滚动页面的时候,当图片进入可视区域时再加载,这样可以明显的提高页面加载速度,而更少的图片并发请求数,也可以大大的减轻服务器的压力,可谓一举多得。
图片延迟加载的原理比较简单,先把图片的真实地址写在自定义的一个属性上,比如 data-url(HTML5中以 data- 开头的自定义属性都是合法的),src 地址最好不要空着,放一个 1×1 的全透明占位图片就行了,如:
<img src="images/transparent_img.png" data-url="images/real_img.jpg">
也可以加上如果用户禁用JS后的替代方案:
<img src="images/transparent_img.png" data-url="images/real_img.jpg" > <noscript><img src="images/real_img.jpg" ></noscript>
当页面滚动的时候开始计算图片是否处在当前窗口的可视区域,如果在的话,就把 src 的假地址替换成 data-url 的真实地址,ok,原理就是这样,很简单吧。
网上详细讲解这个效果的很多,例子也不少,大家有兴趣可以搜一下。最近在看前端性能优化方面的东西,正好上午没事想写个插件练练手,就写了这个简单的延迟加载的插件,基于 jQuery,代码不多,只有 60 行:
/* * 基于jQuery的图片延迟加载插件 * by Hey@feelcss (http://www.feelcss.com/) * 2012-07-12 */ ;(function($){ $.fn.imgLazyLoading = function(options){ //定义需要的参数的初始值,并合并options对象到set对象 var set = $.extend({ url : "data-url", fadeIn : 0 }, options || {}); var cache = []; $(this).each(function(){ var nodeName = this.nodeName.toLowerCase(); var url = $(this).attr(set.url); //获取每个元素的信息 var data = { obj : $(this), url : url, tag : nodeName } cache.push(data); }); var lazyLoading = function(){ $.each(cache,function(i, e){ var obj = e.obj, url = e.url, tag = e.tag; if(obj){ var winHeight = $(window).height(); //当前窗口高度 var scrolltop = $(window).scrollTop(); //滚动条偏移高度 var oTop = obj.offset().top; //图片相对高度 //判断是否在当前窗口内 if((oTop-scrolltop) > 0 && (oTop-scrolltop) < winHeight){ if(tag === "img"){ if(set.fadeIn){ //渐出效果 obj.fadeIn(set.fadeIn); } //给src属性赋值 obj.attr("src", url); }else{ return false; } e.obj = null; } } }); } //加载后立即执行 lazyLoading(); //执行滚动,触发事件 $(window).bind("scroll", lazyLoading); }; })(jQuery);
使用非常简单,先分别引入 jQuery 和 jquery.imgLazyLoading.js,此插件的方法名就是 imgLazyLoading,直接 element.imgLazyLoading() 就可以了,很简单:
$(".lazyLoading").imgLazyLoading();
插件比较简单,可以接收两个参数:
url: 记录图片真实地址的属性名
fadeIn: 图片渐出效果以及渐出时间
$(".lazyLoading").imgLazyLoading({ // 记录图片真实地址的属性名 url : "data-url", // 图片渐出效果以及渐出时间 fadeIn : 400 });
最后附上例子:
插件难免有考虑不周的地方,如果大家有什么建议或纠正的话,欢迎一起讨论:)