javascript 延迟加载技术(lazyload)简单实现


Posted in Javascript onJanuary 17, 2011

1.前言

懒加载技术(简称lazyload)并不是新技术, 它是js程序员对网页性能优化的一种方案.lazyload的核心是按需加载.在大型网站中都有lazyload的身影,例如谷歌的图片搜索页,迅雷首页,淘宝网,QQ空间等.因此掌握lazyload技术是个不错的选择,可惜jquery插件lazy load官网(http://www.appelsiini.net/projects/lazyload)称不支持新版浏览器。

2.lazyload在什么场合中应用比较合适?

涉及到图片,falsh资源 , iframe, 网页编辑器(类似FCK)等占用较大带宽,且这些模块暂且不在浏览器可视区内,因此可以使用lazyload在适当的时候加载该类资源.避免网页打开时加载过多资源,让用户等待太久.

3.如何实现lazyload?

lazyload的难点在如何在适当的时候加载用户需要的资源(这里用户需要的资源指该资源呈现在浏览器可视区域)。因此我们需要知道几点信息来确定目标是否已呈现在客户区,其中包括:

1.可视区域相对于浏览器顶端位置

2.待加载资源相对于浏览器顶端位置.

在得到以上两点数据后,通过如下函数,便可得出某对象是否在浏览器可视区域了.

//返回浏览器的可视区域位置 

 function getClient(){ 


 var l,t,w,h; 


 l = document.documentElement.scrollLeft || document.body.scrollLeft; 


 t = document.documentElement.scrollTop || document.body.scrollTop; 


 w = document.documentElement.clientWidth; 


 h = document.documentElement.clientHeight; 


 return {'left':l,'top':t,'width':w,'height':h} ; 

 } 

//返回待加载资源位置 

 function getSubClient(p){ 


 var l = 0,t = 0,w,h; 


 w = p.offsetWidth ; 


 h = p.offsetHeight; 


while(p.offsetParent){ 


l += p.offsetLeft ; 


 t += p.offsetTop ; 


 p = p.offsetParent; 

} 

return {'left':l,'top':t,'width':w,'height':h } ; 
}

其中 函数 getClient()返回浏览器客户区区域信息,getSubClient()返回目标模块区域信息。此时确定目标模块是否出现在客户区实际上是确定如上两个矩形是否相交.

//判断两个矩形是否相交,返回一个布尔值 

 function intens(rec1,rec2){ 


 var lc1,lc2,tc1,tc2,w1,h1; 


 lc1 = rec1.left + rec1.width / 2; 


 lc2 = rec2.left + rec2.width / 2; 


tc1 = rec1.top + rec1.height / 2 ; 


 tc2 = rec2.top + rec2.height / 2 ; 


 w1 = (rec1.width + rec2.width) / 2 ; 


 h1 = (rec1.height + rec2.height) / 2; 


 return Math.abs(lc1 - lc2) < w1 && Math.abs(tc1 - tc2) < h1 ; 

 }

现在基本上可以实现延时加载了,接下来,我们在 window.onscroll 事件中编写一些代码监控目标区域是否呈现在客户区.

<div style = "width:100px; height:3000px"></div> 

<div id = "d1" style = "width:50px; height:50px; background:red;position:absolute; top:1000px"> 

</div> 

 var d1 = document.getElementById("d1"); 

 window.onscroll = function(){ 

 
var prec1 = getClient(); 


var prec2 = getSubClient(d1); 


 if(intens(prec1,prec2)){ 

 

alert("true") 

   
} 

}

我们只需要在弹出窗口的地方加载我们需要的资源.

这里值得注意的是:目标对象呈现在客户区域时,会随着滚动而不断的弹出窗口.因此我们需要在弹出第一个窗口后取消对该区域的监测,这里用一个数组来收集需要监测的对象。还需要注意:因为onscroll事件和onresize事件都会改变游览器可视区域信息,因此在该类事件触发后需要重新计算目标对象是否在可视区域,这里用autocheck()函数实现.(迅雷首页的lazyload没有在onresize事件中重新计算目标对象是否在浏览器可视区域,因此如果先将浏览器窗口缩小到一定尺寸后滚动到需要加载图片的区域后点击最大化,图片加载不出来,呵呵,以后需要注意了).

增加元素:<div id = "d2" style = "width:50px; height:50px; background:blue;position:absolute; top:2500px">

//比较某个子区域是否呈现在浏览器区域 

function jiance(arr,prec1,callback){ 

 var prec2; 

 for(var i = arr.length - 1 ; i >= 0 ;i--){ 


 if(arr[i]){ 


 prec2 = getSubClient(arr[i]); 


 if(intens(prec1,prec2)){ 



callback(arr[i]); 



 //加载资源后,删除监测 


 
 delete arr[i]; 



} 


} 

 } 

} 

//检测目标对象是否出现在客户区 

function autocheck(){ 


 var prec1 = getClient(); 


jiance(arr,prec1,function(obj){ 



//加载资源... 


 alert(obj.innerHTML) 


}) 

} 

//子区域一 

 var d1 = document.getElementById("d1"); 

 //子区域二 

var d2 = document.getElementById("d2"); 

 //需要按需加载区域集合 

var arr = [d1,d2]; 

 window.onscroll = function(){ 


 //重新计算 


 autocheck(); 

} 

window.onresize = function(){ 


 //重新计算 


 autocheck(); 

}

现在我们只需要在弹窗的地方加载我们需要的资源了.源码就不贴出来了.如果需要的朋友,或着存在疑问的地方,可以联系我.

Javascript 相关文章推荐
checkbox 多选框 联动实现代码
Oct 22 Javascript
基于jquery的动态创建表格的插件
Apr 05 Javascript
JS获取计算机mac地址以及IP的实现方法
Jan 08 Javascript
setInterval与clearInterval的使用示例代码
Jan 28 Javascript
jQuery内容过滤选择器用法分析
Feb 10 Javascript
js图片放大镜效果实现方法详解
Oct 28 Javascript
vue.js如何更改默认端口号8080为指定端口的方法
Jul 14 Javascript
vue-router传递参数的几种方式实例详解
Nov 13 Javascript
js序列化和反序列化的使用讲解
Jan 19 Javascript
详解vue 图片上传功能
Apr 30 Javascript
vue+koa2搭建mock数据环境的详细教程
May 18 Javascript
一行JavaScript代码如何实现瀑布流布局
Dec 11 Javascript
关于COOKIE个数与大小的问题
Jan 17 #Javascript
js实现的跟随鼠标移动的时钟效果(中英文日期显示)
Jan 17 #Javascript
Jquery 插件开发笔记整理
Jan 17 #Javascript
JQuery学习笔记 nt-child的使用
Jan 17 #Javascript
Jquery知识点三 jquery表单对象操作
Jan 17 #Javascript
基于jquery的返回顶部效果(兼容IE6)
Jan 17 #Javascript
jquery+ajax每秒向后台发送请求数据然后返回页面的代码
Jan 17 #Javascript
You might like
PHP学习笔记 用户注册模块用户类以及验证码类
2011/09/20 PHP
PHP中extract()函数的妙用分析
2012/07/11 PHP
PHP的preg_match匹配字符串长度问题解决方法
2014/05/03 PHP
jQuery中:reset选择器用法实例
2015/01/04 Javascript
jQuery对象与DOM对象之间的相互转换
2015/03/03 Javascript
每天一篇javascript学习小结(Array数组)
2015/11/11 Javascript
详解使用angular的HttpClient搭配rxjs
2017/09/01 Javascript
原生JS实现$.param() 函数的方法
2018/08/10 Javascript
javascript获取select值的方法完整实例
2019/06/20 Javascript
如何给element添加一个抽屉组件的方法步骤
2019/07/14 Javascript
vue element-ui el-date-picker限制选择时间为当天之前的代码
2019/11/07 Javascript
JS控制只能输入数字并且最多允许小数点两位
2019/11/24 Javascript
[36:33]完美世界DOTA2联赛PWL S2 LBZS vs Forest 第二场 11.29
2020/12/02 DOTA
Python牛刀小试密码爆破
2011/02/03 Python
python发布模块的步骤分享
2014/02/21 Python
Python2.7编程中SQLite3基本操作方法示例
2017/08/09 Python
Python冲顶大会 快来答题!
2018/01/17 Python
解决python selenium3启动不了firefox的问题
2018/10/13 Python
python实现扫描局域网指定网段ip的方法
2019/04/16 Python
python机器学习包mlxtend的安装和配置详解
2019/08/21 Python
python提取xml里面的链接源码详解
2019/10/15 Python
python字符串的拼接方法总结
2019/11/18 Python
利用pandas向一个csv文件追加写入数据的实现示例
2020/04/23 Python
BrandAlley英国:法国折扣奢侈品网上零售商
2017/07/03 全球购物
Bose法国官网:购买耳机、扬声器、家庭影院、专业音响
2017/12/21 全球购物
简历自我评价模版
2014/01/31 职场文书
白酒市场营销方案
2014/02/25 职场文书
2015年上半年计生工作总结
2015/03/30 职场文书
2015年设计师个人工作总结
2015/04/25 职场文书
胡桃夹子观后感
2015/06/11 职场文书
元旦联欢晚会主持词
2015/07/01 职场文书
高中团支书竞选稿
2015/11/21 职场文书
小学秋季运动会加油口号及加油稿
2019/08/19 职场文书
如何在Python中创建二叉树
2021/03/30 Python
详解python的内存分配机制
2021/05/10 Python
特别篇动画《总之就是非常可爱 ~制服~》PV公开,2022年夏季播出
2022/04/04 日漫