`

深入懒加载

阅读更多

转:http://blog.csdn.net/huli870715/article/details/8126519

懒加载(LazyLoad)一直是前端的优化方案之一。它的核心思想是:当用户想看页面某个区域时,再加载该区域的数据。这在一定程度上减轻了服务器端的压力,也加快了页面的呈现速度。

   懒加载多用于图片,因为它属于流量的大头。最典型的懒加载实现方案是先将需要懒加载的图片的src隐藏掉,这样图片就不会下载,然后在图片需要呈现给用户时再加上src属性。

   公司内部库的懒加载正是采用这种方案。它会遍历页面中所有的图片,将其src缓存起来后删除图片的src属性,当图片进入用户的可视区域后再为图片附加src属性。这种方案存在着以下不足:

   ① 在IE和FF下,懒加载的脚本运行时,有部分图片已经于服务器建立链接,这部分abort掉,再在滚动时延迟加载,反而增加了链接数。

   ② 在chrome下,由于webkit内核bug,导致无法abort掉下载,懒加载脚本完全无用。

   ③ 它只能针对图片的懒加载,但无法懒加载页面的某个模块(即延迟渲染页面的DOM节点)。

   

   因此,在原有的技术方案之上,必须实现新的方案来解决这些问题。受到淘宝的懒加载模块启发,思路如下:

   ① 提供一种方式来让我们手动为页面中每个需要懒加载的图片缓存它的src属性,例如:原来的图片为<img src="xxx.jpg" />,现在改为<img data-src="xxx.jpg">。这样,页面在解析的时候,所有懒加载的图片在所有的浏览器下都不会下载,图片进入视野区域时再将 data-src赋值给src属性。

   ② 提供延迟加载页面模块的方案。将研究发现,textarea是个不错的容器,浏览器会将该标签内的内容当作普通文本看待。因此,可以将页面中需要懒加载的模块放入textarea容器中,带需要的时候再将其取出。淘宝美食网正是大量运用了模块延迟加载方案。http://chi.taobao.com/market/food/auto.php?spm=885.125570.154248.13.F5s7Bt

基于上述思路,我写了一个懒加载的组件。该组件基于jquery,提供的接口如下:

[javascript] view plaincopy
  1. return {  
  2.     init : _init,  
  3.     addCallBack : _addCallBack  
  4. };  

init函数可以初始化该组件,它提供给我们的自定义选项如下:

 

[javascript] view plaincopy
  1. var config = {  
  2.     mod : 'auto'//分为auto和manul  
  3.     IMG_SRC_DATA : 'img-lazyload',  
  4.     AREA_DATA_CLS : 'area-datalazyload'  
  5. };  

mod 分为自动和手动模式,自动模式正是前面讨论到的目前存在的实现方案,而手动方式是后来讨论的方案①,在手动方式下,我们需要将每个需要懒加载的图片的 src属性缓存到一个用户可以自定义的属性中,默认为'img-lazyload',即原始的图片改为<img img-lazyload='xxx.jpg'>。

此外,不管是自动模式和手动模式下,都可以进行模块的懒加载,这时候,需要在每个模块的外层添加textarea容器,并且,将其visibility属性设置为hidden,class设置为一个用户可以自定义的值,默认为'area-datalazyload'。

  实例如下:

 

[javascript] view plaincopy
  1. //自动模式  
  2. datalazyload.init({  
  3.     'mod' :auto  
  4. });  
  5.   
  6. //手动模式  
  7. datalazyload.init({  
  8.     'mod' :manual,  
  9.    'IMG_SRC_DATA'  : 'data-src'  
  10. });  

addCallback是特定元素即将出现时的回调函数。调用如下:

 

  1. datalazyload.addCallback($el,function(event){  
  2.      //TO DO  
  3. })  

其中$el是某个需要延迟加载的jquery对象,function是自定义的回调函数。

 

组件适用场景:① 有许多图片的页面,例如游戏特权首页:http://vip.qq.com/game.html

              ② 有许多模块,并且每个模块分工明确的页面,例如淘宝美食:http://chi.taobao.com/market/food/auto.php?spm=885.125570.154248.13.F5s7Bt

 

组件如下:

 

[javascript] view plaincopy
  1. /** 
  2.  * @fileOverview 数据懒加载组件 
  3.  * @require jQuery 
  4.  */  
  5.   
  6. datalazyload = (function($){  
  7.   
  8.     var config = {  
  9.         mod : 'auto'//分为auto和manul  
  10.         IMG_SRC_DATA : 'img-lazyload',  
  11.         AREA_DATA_CLS : 'area-datalazyload'  
  12.     };  
  13.       
  14.       
  15.     var IMG_SRC_DATA = '';  
  16.     var AREA_DATA_CLS = '';  
  17.       
  18.     //用来存放需要懒加载的图片和数据块  
  19.     var imgArr = [];  
  20.     var areaArr = [];  
  21.       
  22.     //支持用户回调的事件类型  
  23.     var eventType = 'lazy';  
  24.       
  25.     /** 
  26.      * 提供给外部的接口 
  27.      * @param {Object} [userConfig] 用户自定义配置 
  28.      * @private 
  29.     */    
  30.     function _init(userConfig) {  
  31.         config = $.extend(config,userConfig);  
  32.         console.log(config);  
  33.         IMG_SRC_DATA = config.IMG_SRC_DATA;  
  34.         AREA_DATA_CLS = config.AREA_DATA_CLS;  
  35.         _filterItems();  
  36.         _initEvent();  
  37.     }  
  38.       
  39.     /** 
  40.      * 处理需要懒加载的图片和数据块的入口 
  41.      * @private 
  42.     */    
  43.     function _filterItems() {  
  44.         _filterImgs();  
  45.         _filterAreas();  
  46.     }  
  47.   
  48.     /** 
  49.      * 事件绑定 
  50.      * @private 
  51.     */        
  52.     function _initEvent() {  
  53.         $(window).scroll(_eventHandler);  
  54.         $(window).resize(_eventHandler);  
  55.         _eventHandler();  
  56.     }  
  57.   
  58.     /** 
  59.      * 处理需要懒加载的图片 
  60.      * @private 
  61.     */    
  62.     function _filterImgs() {  
  63.         if (config.mod === 'auto') {   
  64.             //自动模式  
  65.             var $imgs = $("img");  
  66.             $imgs.each(function() {  
  67.                 imgArr.push(this);  
  68.                 var $img = $(this);  
  69.                 $img.targetY = _getTargetY($img[0]);//先计算出每个图片距离页面顶部的高度,避免在事件事件处理函数中进行大量重复计算  
  70.                 var dataSrc = $img.attr(IMG_SRC_DATA);  
  71.                 //对于已存在IMG_SRC_DATA的,可能其它实例处理过,我们直接跳过去  
  72.                 if (!dataSrc) {  
  73.                     $img.attr(IMG_SRC_DATA,$img.attr('src'));  
  74.                     $img.removeAttr('src');  
  75.                 }  
  76.             });  
  77.         } else {  
  78.             //手动模式下,已经在需要懒加载的IMG中设置了IMG_SRC_DATA属性,所以不作任何处理  
  79.             var $imgs = $("img["+IMG_SRC_DATA+"]");  
  80.             $imgs.each(function() {  
  81.                 imgArr.push(this);  
  82.                 var $img = $(this);  
  83.                 $img.targetY = _getTargetY($img[0]);//先计算出每个图片距离页面顶部的高度,避免在事件事件处理函数中进行大量重复计算  
  84.             });  
  85.         }  
  86.     }  
  87.       
  88.     /** 
  89.      * 处理需要懒加载的数据块 
  90.      * @private 
  91.     */    
  92.     function _filterAreas() {  
  93.         var $areas = $("textarea[class='"+AREA_DATA_CLS+"']");  
  94.         $areas.each(function() {  
  95.             areaArr.push(this);  
  96.             var $area = $(this);  
  97.             $area.targetY = _getTargetY($area[0]);  
  98.         });  
  99.     }  
  100.   
  101.     /** 
  102.      * window节点的scroll和resize的事件处理函数 
  103.      * @private 
  104.     */  
  105.     function _eventHandler() {  
  106.         $.each(imgArr,function(i,el){  
  107.             if (el !== undefined) {  
  108.                 var $img = $(el);  
  109.                 if (_checkBounding($img)) {  
  110.                     $img.attr('src',$img.attr(IMG_SRC_DATA));  
  111.                     $img.trigger(eventType);  
  112.                     $img.unbind(eventType);  
  113.                     delete imgArr[i];  
  114.                 }  
  115.             }  
  116.         });  
  117.         $.each(areaArr,function(i,el){  
  118.             if (el !== undefined) {  
  119.                 var $area = $(el);  
  120.                 if (_checkBounding($area)) {  
  121.                     $area.hide();  
  122.                     $area.removeClass(AREA_DATA_CLS);  
  123.                     var $div = $("<div></div>");  
  124.                     $div.insertBefore($area);  
  125.                     $div.html($area.val());  
  126.                     delete areaArr[i];  
  127.                 }  
  128.             }  
  129.         });       
  130.           
  131.     }  
  132.     /** 
  133.      * 检查需要懒加载的节点是否进入可视区域 
  134.      * @param {jQuery Object} [el] 
  135.      * @private 
  136.     */    
  137.     function _checkBounding($el) {  
  138.         var scrollY = document.body.scrollTop || document.documentElement.scrollTop || window.pageYOffset || 0;//页面滚动条高度  
  139.         var seeY = window.innerHeight || document.documentElement.clientHeight;//浏览器可视区域高度  
  140.         if ($el.targetY) {  
  141.             var targetY = $el.targetY;  
  142.         } else {  
  143.             var targetY = _getTargetY($el[0]);  
  144.         }  
  145.           
  146.         //当目标节点进入可使区域  
  147.         if (Math.abs(targetY - scrollY) < seeY) {  
  148.             return true;  
  149.         } else {  
  150.             return false;  
  151.         }  
  152.     }   
  153.       
  154.     /** 
  155.      * 获取目标节点距离页面顶部高度 
  156.      * @param {HTML Element} [el] 
  157.      * @private 
  158.     */    
  159.     function _getTargetY(el) {  
  160.         var tp = el.offsetTop;  
  161.         if (el.offsetParent) {  
  162.             while (el = el.offsetParent) {  
  163.                 tp += el.offsetTop;  
  164.             }  
  165.         }  
  166.         return tp;  
  167.     }  
  168.       
  169.     /** 
  170.      * 特定元素即将出现时的回调函数 
  171.      * @param {jQuery Obj} [$el]  
  172.      * @param {Function} [func] 
  173.      * @private 
  174.     */        
  175.     function _addCallBack($el,func) {  
  176.         $el.bind(eventType,function(event) {  
  177.             func.call($el,event);  
  178.         });  
  179.     }  
  180.     return {  
  181.         init : _init,  
  182.         addCallBack : _addCallBack  
  183.     };  
  184.       
  185. })(jQuery); 
分享到:
评论

相关推荐

    懒加载案例lazyload

    在这个"懒加载案例-lazyload"中,我们可以深入探讨以下几个关键知识点: 1. **懒加载原理**: - **可见性检测**:懒加载的核心在于判断元素是否在用户的视口范围内。这通常通过计算元素距离浏览器窗口的距离和用户...

    jquery懒加载版本表格树GridTree.zip

    《jQuery懒加载版本表格树GridTree详解》 在IT领域,高效的数据呈现是提升用户体验的关键。面对大数据量的处理,传统的加载方式往往会导致页面加载缓慢,用户体验下降。为解决这一问题,"jQuery懒加载版本表格树...

    懒加载版本表格树

    通过分析和学习这些文件,我们可以深入理解懒加载版本表格树的实现细节和工作原理。 总的来说,懒加载表格树是大数据量场景下的理想选择,它结合了高效的数据加载策略和用户友好的界面交互,提高了应用的性能和用户...

    JQuery实现页面图片懒加载效果仅需两行代码

    在网页设计中,为了提高页面加载速度和用户体验,懒加载(Lazy Load)技术被广泛应用。尤其是在图片密集型的网站上,非首屏的图片可以延迟加载,直到用户滚动到相应位置时才开始加载,这样可以显著减少首屏加载时间...

    整合图片懒加载及百度地图定位与显示

    本文将详细讲解如何整合这两种技术,以"整合图片懒加载及百度地图定位与显示"为主题进行深入探讨。 **图片懒加载** 图片懒加载是一种网页优化技术,它推迟非可视区域内图片的加载,直到用户滚动页面使这些图片进入...

    帆软报表填报预览下的懒加载下拉树控件

    "填报预览下的懒加载下拉树控件"是帆软报表中的一种高级特性,旨在提高用户体验和性能优化。 首先,我们要理解什么是“填报预览”。在帆软报表中,填报是指用户可以在报表设计完成后,根据实际业务需求填写数据,这...

    图片懒加载文件jquery插件库EasyLazyload

    `jQuery EasyLazyload` 插件库基于广泛使用的jQuery框架开发,它简化了图片懒加载的实现过程,让开发者无需深入了解底层机制就能轻松地在网站上应用。以下是对这个插件库的一些核心知识点的详细解释: 1. **基本...

    jquery表格树插件GridTree懒加载版本(开源,含demo)

    《jQuery表格树插件GridTree懒加载版本:高效处理大数据量的解决方案》 在Web开发中,处理大数据量的表格往往是一项挑战。传统的表格展示方式可能导致页面加载缓慢,用户体验下降。为了解决这一问题,出现了jQuery...

    div盒子内容的懒加载

    本文将深入探讨“div盒子内容的懒加载”这一主题,包括其原理、实现方法以及为何在APP中专用于div盒子。 懒加载,又称惰性加载,是一种延迟加载策略。它避免一次性加载页面所有内容,而是只在用户需要时才加载相关...

    jQuery懒加载插件页面滚动加载数据代码

    下面我们将深入探讨jQuery懒加载的工作原理、实现方法以及相关代码。 首先,理解懒加载的基本概念。懒加载(Lazy Loading)是一种延迟加载策略,仅在用户滚动到可视区域时才加载图像或其他资源。这样可以避免在页面...

    jQuery8种不同的懒加载loading效果

    本文将深入探讨jQuery中的8种不同的懒加载loading效果及其相关知识点。 一、基本概念 懒加载是一种优化策略,它只在用户滚动到可视区域时才加载图像或特定内容,而不是一次性加载整个页面。这样可以减少初始页面...

    Fragment的懒加载

    本教程将深入探讨Fragment的懒加载及其实践。 首先,理解懒加载的概念:懒加载是一种延迟加载策略,即在真正需要时才加载数据或资源,而不是在初始化时一次性全部加载。在Fragment中,这通常意味着在Fragment首次...

    垂直瀑布流 懒加载

    通过分析这些文件,我们可以更深入地理解瀑布流和懒加载的具体实现细节。 总的来说,"垂直瀑布流 懒加载"是一个结合了前端布局技巧和优化策略的实例,对于提升网页性能和用户体验具有重要意义。通过学习和实践这样...

    Fragment+viewpager懒加载方案

    在这个“Fragment+ViewPager懒加载方案”中,我们将深入探讨如何将这一策略应用于Fragment与ViewPager的结合使用,以实现更高效的资源管理。 首先,让我们理解Fragment和ViewPager的基本概念。Fragment是Android中...

    ViewPager的懒加载

    下面我们将深入探讨ViewPager的懒加载原理以及如何实现。 1. **ViewPager的工作原理** ViewPager通过PagerAdapter来管理页面,PagerAdapter负责创建并返回页面(通常为Fragment)。当用户滑动页面时,ViewPager会...

    Fragment懒加载 volley Picasso

    Fragment懒加载、Volley网络请求库以及Picasso图片加载库是三个非常关键的技术点,它们能够帮助我们构建高效且流畅的应用。让我们逐一深入探讨这三个知识点。 首先,`Fragment懒加载`是一种优化策略,用于处理...

    jQuery懒加载点击加载图片代码.zip

    本文将深入解析“jQuery懒加载点击加载图片代码”,并探讨如何在不支持IE6、7、8的环境中实现这一功能。 一、jQuery懒加载基础 jQuery懒加载是一种优化网页性能的技术,它延迟加载那些不在用户视口范围内的图像,...

    懒加载,响应式

    首先,让我们来深入理解“懒加载”(Lazy Loading)。懒加载是一种延迟加载技术,它允许网页在用户滚动到相关部分时才加载图片、视频或某些特定的模块,而不是一次性加载所有内容。这显著减少了初始页面加载时间,...

    图片视频懒加载.rar

    "图片视频懒加载"技术正是为了解决这个问题而诞生的。这个压缩包"图片视频懒加载.rar"包含了一些关键文件,用于实现这一功能。我们将深入探讨这个技术以及其中涉及到的知识点。 首先,"图片视频懒加载"是一种优化...

Global site tag (gtag.js) - Google Analytics