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 相关文章推荐
TFDN图片播放器 不错自动播放
Oct 03 Javascript
分享一个asp.net pager分页控件
Jan 04 Javascript
jQuery 追加元素的方法如append、prepend、before
Jan 16 Javascript
jquery显示loading图片直到网页加载完成的方法
Jun 25 Javascript
全面解析JS字符串和正则表达式中的match、replace、exec等函数
Jul 01 Javascript
Angular ng-repeat 对象和数组遍历实例
Sep 14 Javascript
微信js-sdk上传与下载图片接口用法示例
Oct 12 Javascript
jquery做个日期选择适用于手机端示例
Jan 10 Javascript
详解使用vue实现tab 切换操作
Jul 03 Javascript
JavaScript实现的数字与字符串转换功能示例
Aug 23 Javascript
ES6 Array常用扩展的应用实例分析
Jun 26 Javascript
原生js+canvas实现下雪效果
Aug 02 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自定文件保存session的方法
2014/12/10 PHP
php对数组内元素进行随机调换的方法
2015/05/12 PHP
php使用Swoole实现毫秒级定时任务的方法
2020/09/04 PHP
jQuery 锚点跳转滚动条平滑滚动一句话代码
2010/04/30 Javascript
基于jquery的文本框与autocomplete结合使用(asp.net+json)
2012/05/30 Javascript
让AJAX不依赖后端接口实现方案
2012/12/03 Javascript
JavaScript中判断整数的多种方法总结
2014/11/08 Javascript
FF(火狐)浏览器无法执行window.close()解决方案
2014/11/13 Javascript
理解javascript定时器中的setTimeout与setInterval
2016/02/23 Javascript
js阻止浏览器默认行为触发的通用方法(推荐)
2016/05/15 Javascript
原生js实现键盘控制div移动且解决停顿问题
2016/12/05 Javascript
js实现自定义进度条效果
2017/03/15 Javascript
js仿京东放大镜效果
2020/08/09 Javascript
python3使用urllib模块制作网络爬虫
2016/04/08 Python
Zabbix实现微信报警功能
2016/10/09 Python
Python实现的当前时间多加一天、一小时、一分钟操作示例
2018/05/21 Python
python定时关机小脚本
2018/06/20 Python
python判断设备是否联网的方法
2018/06/29 Python
python 实现12bit灰度图像映射到8bit显示的方法
2019/07/08 Python
Django REST Framework序列化外键获取外键的值方法
2019/07/26 Python
pycharm开发一个简单界面和通用mvc模板(操作方法图解)
2020/05/27 Python
python如何代码集体右移
2020/07/20 Python
python matplotlib工具栏源码探析三之添加、删除自定义工具项的案例详解
2021/02/25 Python
丝芙兰中国官方商城:SEPHORA中国
2018/01/10 全球购物
全球在线商店:BerryLook
2019/04/14 全球购物
英国豪华家具和家居用品购物网站:Teddy Beau
2020/10/12 全球购物
得到Class的三个过程是什么
2012/08/10 面试题
写给女朋友的道歉信
2014/01/12 职场文书
市场营销个人求职信范文
2014/02/02 职场文书
环保公益广告语
2014/03/13 职场文书
《埃及的金字塔》教学反思
2014/04/07 职场文书
大学生自荐信怎么写
2015/03/26 职场文书
学生会部长竞选稿
2015/11/19 职场文书
了解Redis常见应用场景
2021/06/23 Redis
Pycharm远程调试和MySQL数据库授权问题
2022/03/18 MySQL
Fluentd搭建日志收集服务
2022/09/23 Servers