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 相关文章推荐
IE6/7/8/9不支持exec的简写方式
May 25 Javascript
深入理解JavaScript系列(2) 揭秘命名函数表达式
Jan 15 Javascript
js实现右下角可关闭最小化div(可用于展示推荐内容)
Jun 24 Javascript
JQuery表格内容过滤的实现方法
Jul 05 Javascript
javascript实现数组中的内容随机输出
Aug 11 Javascript
JavaScript Split()方法
Dec 18 Javascript
javascript中arguments,callee,caller详解
Mar 16 Javascript
vue.js的提示组件
Mar 02 Javascript
Vue表单demo v-model双向绑定问题
Jun 29 Javascript
JS实现音乐导航特效
Jan 06 Javascript
vue-iview动态新增和删除的方法
Jun 17 Javascript
如何使用 vue-cli 创建模板项目
Nov 19 Vue.js
关于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
使用eAccelerator加密PHP程序
2008/10/03 PHP
php数字转汉字代码(算法)
2011/10/08 PHP
PHP中把数据库查询结果输出为json格式简单实例
2015/04/09 PHP
php简单统计在线人数的方法
2016/05/10 PHP
全面了解PHP中的全局变量
2016/06/17 PHP
PHP+Ajax异步带进度条上传文件实例
2016/11/01 PHP
swoole和websocket简单聊天室开发
2017/11/18 PHP
javascript Base类 包含基本的方法
2009/07/22 Javascript
javascript 继承实现方法
2009/08/26 Javascript
一个基于jquery的文本框记数器
2012/09/19 Javascript
基于jQuery实现模拟页面加载进度条
2013/04/01 Javascript
javascript获取浏览器类型和版本的方法(js获取浏览器版本)
2014/03/13 Javascript
jQuery根据元素值删除数组元素的方法
2015/06/24 Javascript
JQ技术实现注册页面带有校验密码强度
2015/07/27 Javascript
JS实现超简单的仿QQ折叠菜单效果
2015/09/21 Javascript
js实现本地时间同步功能
2017/08/26 Javascript
vue.js实现会动的简历(包含底部导航功能,编辑功能)
2019/04/08 Javascript
解决layer.prompt无效的问题
2019/09/24 Javascript
Python的Django框架中设置日期和字段可选的方法
2015/07/17 Python
微信跳一跳小游戏python脚本
2018/01/05 Python
Python 按字典dict的键排序,并取出相应的键值放于list中的实例
2019/02/12 Python
手把手教你Python yLab的绘制折线图的画法
2019/10/23 Python
基于Python中的yield表达式介绍
2019/11/19 Python
pycharm实现在子类中添加一个父类没有的属性
2020/03/12 Python
通过代码实例解析Pytest运行流程
2020/08/20 Python
Django框架实现在线考试系统的示例代码
2020/11/30 Python
日本网路线上商品代购服务:转送JAPAN
2016/08/05 全球购物
Ajax主要包含了哪些技术
2014/06/12 面试题
2014年审计工作总结
2014/11/17 职场文书
2014年信息技术工作总结
2014/12/16 职场文书
病危通知单
2015/04/17 职场文书
导盲犬小Q观后感
2015/06/11 职场文书
贷款收入证明格式
2015/06/24 职场文书
2015年中学图书馆工作总结
2015/07/22 职场文书
2015年教师个人业务工作总结
2015/10/23 职场文书
HTML5之高度塌陷问题的解决
2022/06/01 HTML / CSS