jquery lazyload延迟加载技术的实现原理分析


Posted in Javascript onJanuary 24, 2011

前言

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

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

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

如何实现lazyload?

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

  • 可视区域相对于浏览器顶端位置;
  • 待加载资源相对于浏览器顶端位置。

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

// 返回浏览器的可视区域位置 
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="div1" style="width:50px; height:50px; background:red; position:absolute; top:1000px"> 
</div>

var div1 = document.getElementById("div1"); 
window.onscroll = function(){ 
var prec1 = getClient(); 
var prec2 = getSubClient(div1); 
if (intens(prec1, prec2)) { 
alert("true"); 
} 
};

我们只需要在弹出窗口的地方加载我们需要的资源。
这里值得注意的是 : 目标对象呈现在客户区域时,会随着滚动而不断的弹出窗口。因此我们需要在弹出第一个窗口后取消对该区域的监测,这里用一个数组来收集需要监测的对象,同时将监测的逻辑抽出来。同时需要注意 onscroll事件和onresize事件都会改变游览器可视区域信息,因此在该类事件触发后需要重新计算,这里用autocheck()函数实现。
增加元素 :
<div id="div2" 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 EasyUI API 中文文档 - Spinner微调器使用
Oct 21 Javascript
javaScript让文本框内的最后一个文字的后面获得焦点实现代码
Jan 06 Javascript
鼠标划过实现延迟加载并隐藏层的js代码
Oct 11 Javascript
纯css+js写的一个简单的tab标签页带样式
Jan 28 Javascript
Javascript实现的Map集合工具类完整实例
Jul 31 Javascript
Jq通过td获取同行其它列td的方法
Oct 05 Javascript
基于Javascript实现文件实时加载进度的方法
Oct 12 Javascript
switchery按钮的使用方法
Dec 18 Javascript
再谈Angular4 脏值检测(性能优化)
Apr 23 Javascript
JQuery模拟实现网页中自定义鼠标右键菜单功能
Nov 14 jQuery
了解Javascript中函数作为对象的魅力
Jun 19 Javascript
js实现简单的贪吃蛇游戏
Apr 23 Javascript
11款新鲜的jQuery插件[附所有demo下载]
Jan 24 #Javascript
基于jQuery的输入框无值自动显示指定数据的实现代码
Jan 24 #Javascript
精选的10款用于构建良好易用性网站的jQuery插件
Jan 23 #Javascript
返回对象在当前级别中是第几个元素的实现代码
Jan 20 #Javascript
有趣的JavaScript数组长度问题代码说明
Jan 20 #Javascript
无阻塞加载脚本分析[全]
Jan 20 #Javascript
善用事件代理,警惕闭包的性能陷阱。
Jan 20 #Javascript
You might like
php array_reverse 以相反的顺序返回数组实例代码
2017/04/11 PHP
基于Laravel5.4实现多字段登录功能方法示例
2017/08/11 PHP
PHP利用curl发送HTTP请求的实例代码
2020/07/09 PHP
JS日历 推荐
2006/12/03 Javascript
javascript模拟订火车票和退票示例
2014/04/24 Javascript
Node调试工具JSHint的安装及配置教程
2014/05/27 Javascript
jQuery实现拖拽效果插件的方法
2015/03/23 Javascript
纯js实现无限空间大小的本地存储
2015/06/18 Javascript
jQuery实现信息提示框(带有圆角框与动画)效果
2015/08/07 Javascript
Node.js中JavaScript操作MySQL的常用方法整理
2016/03/01 Javascript
jQuery实现下拉框功能实例代码
2016/05/06 Javascript
Web性能优化系列 10个提升JavaScript性能的技巧
2016/09/27 Javascript
AngularJS实现使用路由切换视图的方法
2017/01/24 Javascript
解决AjaxFileupload 上传时会出现连接重置的问题
2017/07/07 Javascript
JavaScript获取当前url路径过程解析
2019/12/27 Javascript
vue学习笔记之Vue中css动画原理简单示例
2020/02/29 Javascript
vue实现在进行增删改操作后刷新页面
2020/08/05 Javascript
浅谈Python程序与C++程序的联合使用
2015/04/07 Python
使用PyV8在Python爬虫中执行js代码
2017/02/16 Python
获取python文件扩展名和文件名方法
2018/02/02 Python
利用 Flask 动态展示 Pyecharts 图表数据方法小结
2019/09/04 Python
基于Python实现拆分和合并GIF动态图
2019/10/22 Python
如何更改 pandas dataframe 中两列的位置
2019/12/27 Python
Python3 利用face_recognition实现人脸识别的方法
2020/03/13 Python
解决pip install psycopg2出错问题
2020/07/09 Python
python自动化测试三部曲之unittest框架的实现
2020/10/07 Python
校长先进事迹材料
2014/02/01 职场文书
农业局学习党的群众路线教育实践活动心得体会
2014/03/07 职场文书
乡镇消防工作实施方案
2014/03/27 职场文书
员工保密承诺书
2014/05/28 职场文书
团干部培训方案
2014/06/03 职场文书
地球一小时宣传标语
2014/06/24 职场文书
网吧消防安全责任书
2014/07/29 职场文书
房屋租赁意向书范本
2015/05/09 职场文书
关爱空巢老人感想
2015/08/11 职场文书
初二数学教学反思
2016/02/17 职场文书