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 相关文章推荐
jQuery UI的Dialog无法提交问题的解决方法
Jan 11 Javascript
jQuery EasyUI API 中文文档 搜索框
Sep 29 Javascript
jQuery操作checkbox选择(list/table)
Apr 07 Javascript
javascrip关于继承的小例子
May 10 Javascript
javascript页面倒计时实例
Jul 25 Javascript
基于BootStrap Metronic开发框架经验小结【九】实现Web页面内容的打印预览和保存操作
May 12 Javascript
基于js 各种排序方法和sort方法的区别(详解)
Jan 03 Javascript
JS实现的判断方法、变量是否存在功能示例
Mar 28 Javascript
Vue keepAlive 数据缓存工具实现返回上一个页面浏览的位置
May 10 Javascript
小程序实现搜索界面 小程序实现推荐搜索列表效果
May 18 Javascript
JavaScript Event Loop相关原理解析
Jun 10 Javascript
解决vue自定义指令导致的内存泄漏问题
Aug 04 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实现手机归属地查询API接口实现代码
2012/08/27 PHP
PHP实现指定字段的多维数组排序函数分享
2015/03/09 PHP
PHP面向对象学习之parent::关键字
2017/01/18 PHP
php设计模式之原型模式分析【星际争霸游戏案例】
2020/03/23 PHP
特殊字符、常规符号及其代码对照表
2006/06/26 Javascript
JavaScript 动态生成方法的例子
2009/07/22 Javascript
jQuery获取当前对象标签名称的方法
2014/02/07 Javascript
javascript中Number对象的toString()方法分析
2014/12/20 Javascript
jquery实现用户信息修改验证输入方法汇总
2015/07/18 Javascript
jQuery实现的浮动层div浏览器居中显示效果
2017/02/03 Javascript
关于jQuery EasyUI 中刷新Tab选项卡后一个页面变形的解决方法
2017/03/02 Javascript
简单的JS控制button颜色随点击更改的实现方法
2017/04/17 Javascript
Angularjs在360兼容模式下取数据缓存问题的解决办法
2017/06/22 Javascript
Vue中计算属性computed的示例解读
2017/07/26 Javascript
vue中各组件之间传递数据的方法示例
2017/07/27 Javascript
史上最全JavaScript常用的简写技巧(推荐)
2017/08/17 Javascript
vue.js根据代码运行环境选择baseurl的方法
2018/02/28 Javascript
微信小程序实现列表页的点赞和取消点赞功能
2018/11/02 Javascript
微信小程序(订阅消息)功能
2019/10/25 Javascript
Python多线程同步Lock、RLock、Semaphore、Event实例
2014/11/21 Python
浅析Python的web.py框架中url的设定方法
2016/07/11 Python
Python3.4编程实现简单抓取爬虫功能示例
2017/09/14 Python
Flask和Django框架中自定义模型类的表名、父类相关问题分析
2018/07/19 Python
Python多进程与服务器并发原理及用法实例分析
2018/08/21 Python
python实现抖音点赞功能
2019/04/07 Python
通过 Django Pagination 实现简单分页功能
2019/11/11 Python
wxPython实现分隔窗口
2019/11/19 Python
在keras中对单一输入图像进行预测并返回预测结果操作
2020/07/09 Python
sublime3之内网安装python插件Anaconda的流程
2020/11/10 Python
GUESS德国官网:美国牛仔服装品牌
2017/02/14 全球购物
实习生求职自荐信
2014/02/07 职场文书
秋游活动策划方案
2014/02/16 职场文书
感恩母亲节演讲稿
2014/05/07 职场文书
文艺晚会策划方案
2014/06/11 职场文书
涪陵白鹤梁导游词
2015/02/09 职场文书
大学生志愿者心得体会
2016/01/15 职场文书