标签:turn cal ini top 延迟加载 log window details article
-
懒加载(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,提供的接口如下:
- return {
- init : _init,
- addCallBack : _addCallBack
- };
init函数可以初始化该组件,它提供给我们的自定义选项如下:
- var config = {
- mod : ‘auto‘,
- IMG_SRC_DATA : ‘img-lazyload‘,
- AREA_DATA_CLS : ‘area-datalazyload‘
- };
mod 分为自动和手动模式,自动模式正是前面讨论到的目前存在的实现方案,而手动方式是后来讨论的方案①,在手动方式下,我们需要将每个需要懒加载的图片的src属性缓存到一个用户可以自定义的属性中,默认为‘img-lazyload‘,即原始的图片改为<img img-lazyload=‘xxx.jpg‘>。
此外,不管是自动模式和手动模式下,都可以进行模块的懒加载,这时候,需要在每个模块的外层添加textarea容器,并且,将其visibility属性设置为hidden,class设置为一个用户可以自定义的值,默认为‘area-datalazyload‘。
实例如下:
- datalazyload.init({
- ‘mod‘ :auto
- });
-
- datalazyload.init({
- ‘mod‘ :manual,
- ‘IMG_SRC_DATA‘ : ‘data-src‘
- });
addCallback是特定元素即将出现时的回调函数。调用如下:
- datalazyload.addCallback($el,function(event){
- //TO DO
- })
其中$el是某个需要延迟加载的jquery对象,function是自定义的回调函数。
组件适用场景:① 有许多图片的页面,例如游戏特权首页:http://vip.qq.com/game.html
② 有许多模块,并且每个模块分工明确的页面,例如淘宝美食:http://chi.taobao.com/market/food/auto.php?spm=885.125570.154248.13.F5s7Bt。
组件如下:
-
- datalazyload = (function($){
-
- var config = {
- mod : ‘auto‘,
- IMG_SRC_DATA : ‘img-lazyload‘,
- AREA_DATA_CLS : ‘area-datalazyload‘
- };
-
-
- var IMG_SRC_DATA = ‘‘;
- var AREA_DATA_CLS = ‘‘;
-
-
- var imgArr = [];
- var areaArr = [];
-
-
- var eventType = ‘lazy‘;
-
-
- function _init(userConfig) {
- config = $.extend(config,userConfig);
- console.log(config);
- IMG_SRC_DATA = config.IMG_SRC_DATA;
- AREA_DATA_CLS = config.AREA_DATA_CLS;
- _filterItems();
- _initEvent();
- }
-
-
- function _filterItems() {
- _filterImgs();
- _filterAreas();
- }
-
-
- function _initEvent() {
- $(window).scroll(_eventHandler);
- $(window).resize(_eventHandler);
- _eventHandler();
- }
-
-
- function _filterImgs() {
- if (config.mod === ‘auto‘) {
-
- var $imgs = $("img");
- $imgs.each(function() {
- imgArr.push(this);
- var $img = $(this);
- $img.targetY = _getTargetY($img[0]);
- var dataSrc = $img.attr(IMG_SRC_DATA);
-
- if (!dataSrc) {
- $img.attr(IMG_SRC_DATA,$img.attr(‘src‘));
- $img.removeAttr(‘src‘);
- }
- });
- } else {
-
- var $imgs = $("img["+IMG_SRC_DATA+"]");
- $imgs.each(function() {
- imgArr.push(this);
- var $img = $(this);
- $img.targetY = _getTargetY($img[0]);
- });
- }
- }
-
-
- function _filterAreas() {
- var $areas = $("textarea[class=‘"+AREA_DATA_CLS+"‘]");
- $areas.each(function() {
- areaArr.push(this);
- var $area = $(this);
- $area.targetY = _getTargetY($area[0]);
- });
- }
-
-
- function _eventHandler() {
- $.each(imgArr,function(i,el){
- if (el !== undefined) {
- var $img = $(el);
- if (_checkBounding($img)) {
- $img.attr(‘src‘,$img.attr(IMG_SRC_DATA));
- $img.trigger(eventType);
- $img.unbind(eventType);
- delete imgArr[i];
- }
- }
- });
- $.each(areaArr,function(i,el){
- if (el !== undefined) {
- var $area = $(el);
- if (_checkBounding($area)) {
- $area.hide();
- $area.removeClass(AREA_DATA_CLS);
- var $div = $("<div></div>");
- $div.insertBefore($area);
- $div.html($area.val());
- delete areaArr[i];
- }
- }
- });
-
- }
-
- function _checkBounding($el) {
- var scrollY = document.body.scrollTop || document.documentElement.scrollTop || window.pageYOffset || 0;
- var seeY = window.innerHeight || document.documentElement.clientHeight;
- if ($el.targetY) {
- var targetY = $el.targetY;
- } else {
- var targetY = _getTargetY($el[0]);
- }
-
-
- if (Math.abs(targetY - scrollY) < seeY) {
- return true;
- } else {
- return false;
- }
- }
-
-
- function _getTargetY(el) {
- var tp = el.offsetTop;
- if (el.offsetParent) {
- while (el = el.offsetParent) {
- tp += el.offsetTop;
- }
- }
- return tp;
- }
-
-
- function _addCallBack($el,func) {
- $el.bind(eventType,function(event) {
- func.call($el,event);
- });
- }
- return {
- init : _init,
- addCallBack : _addCallBack
- };
-
- })(jQuery);
转载来源:http://blog.csdn.net/huli870715/article/details/8126519
深入懒加载
标签:turn cal ini top 延迟加载 log window details article
原文地址:http://www.cnblogs.com/lishuang1116/p/6533622.html