懒加载是众所周知的减少网页负载,提高性能的方法,不少大型用图片用的多的网站都用到了。
于是我网上一搜,得到一插件:jquery.lazyload 网址:http://www.appelsiini.net/projects/lazyload
然而看了简单的demo之后,仍然只会写这种按照独立的控件来懒加载的代码:
$("img main").lazyload({placeholder:"images/cat_change_cloth.gif"});
既然要做一个肯钻研的人 ,当然不能止步于此。
简单观察以下天猫的首页。
1.主幻灯片div的第一次张幻灯片的加载,是长这样的。未加载完成之前,用户没法切换其他菜单栏。
2.第一张幻灯片加载完成后,是长这样的
你没看错,不是每张图片一个懒加载请求,而是多个图片,一个父div有一个懒加载请求。
那么难点来了。
1. 怎么把加载完成的替代图片放到中间。
2.怎么把懒加载请求转移到多个图片上。
首先,别着急用框架,了解以下jquery.lazyload的实现原理
框架,只针对能设置src的img或者background的div。然而我需要的是能够懒加载整个div中的元素,包括img和其他元素。
以为自己是没看懂,找了一天资料也没找到直接用jquery.lazyload的方法。
好吧,关键时刻,特殊需求,还是自己来写吧。
基本思路:懒加载是通过监听网页滚轮,在指定的时刻加载容器中的图片。那么,加载图片之前要有一个假的容器像用户展示正在加载,加载完成之后将innerhtml填充成真正要展示的。
1.给懒加载的div设置默认背景图片(添加一个class专门展示背景图片bg-loading),用作placeholder
2.第一次监听到滚轮到了懒加载div所在的位置,(等到div中图片全部加载完毕后),去掉bg-loading类,填充innerhtml。
3.此后的每次监听到滚轮滚到指定位置,都不做任何处理 or 最好是不监听了。
好,详细到jquery中的每个操作:
源代码:
1 <!DOCTYPE html> 2 <html> 3 <header> 4 <meta http-equiv="Content-type" content="text/html;charset=utf-8"> 5 <title>jquery ajax</title> 6 <style type="text/css"> 7 .loading{ 8 background:url(https://img.alicdn.com/tps/i1/TB1Q4fJFVXXXXXiXFXXJgUmHVXX-184-38.gif) no-repeat scroll 50% 50%; 9 } 10 </style> 11 <script src="jquery.min.js"></script> 12 <script type="text/javascript"> 13 $(document).ready(function(){ 14 lazyload_cc("loading",400);//body超出窗口400px之后再启用 15 16 }); 17 function lazyload_cc(className,beginHeight){ 18 //功能:当div完整出现在屏幕时,加载。 19 //参数className,需要进行懒加载的元素的类名,要取一样的名字 20 //参数beginHeight,滚动条滚到哪里,开始监听 21 //必须有inited熟悉你给,request-url属性,loading的图片自己准备。可以卸载.loading中。 22 if(!className) { 23 console.error("lazyload_cc方法中缺少className参数"); 24 return; 25 } 26 if(!beginHeight) beginHeight=0; 27 lazyDivList=$("."+className); 28 $(window).scroll(function(){ 29 srcTop=$(window).scrollTop(); 30 if(srcTop>=beginHeight){ 31 lazyDivList.trigger("lazyme",$(window).scrollTop()); 32 } 33 }); 34 lazyDivList.bind("lazyme",function(e,scrTop){ 35 var offset=$(this).offset().top; 36 var interval=$(window).height()-$(this).height();//当前页面可视高度 37 var sumB=offset; 38 var sumS=offset-interval; 39 var url=$(this).attr("request-url"); 40 41 if(scrTop>=sumS && scrTop<=sumB){ 42 $(this).load(url,function(responseTxt,statusTxt,xhr){ 43 if (statusTxt=="success") { 44 $(this).removeClass(className); 45 $(this).unbind("lazyme"); 46 }; 47 }); 48 } 49 }); 50 } 51 </script> 52 53 </header> 54 <body style="height:3000px;"> 55 <div class="loading" style="border:1px solid black;position:absolute;top:800px;left:500px;width:300px;height:400px;" id="lazyu" request-url="requestU.html">abc</div> 56 <div class="loading" style="border:1px solid black;position:absolute;top:1400px;left:500px;width:300px;height:400px;" id="lazyu2" request-url="requestU2.html">abc2</div> 57 </body> 58 <footer> 59 </footer> 60 </html>
完成插件后,以后要实现类似的效果可以直接使用 lazyload_cc(懒加载类名),默认的beginHeight为0;
效果:
div还没到页面中间时,显示正在加载的背景图:
div在页面中间了,显示要展示的详细内容:背景图和原本div.innerhtml都消失了。
源码git地址:https://github.com/HappyBangs/bang_plugins/tree/master/plugin_TmallLazyLoad
建议在虚拟服务器上启动。