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的三种$()
Dec 30 Javascript
Firefox下提示illegal character并出现乱码的原因
Mar 25 Javascript
js获取图片大小的函数代码
Sep 20 Javascript
js函数调用常用方法详解
Dec 03 Javascript
拥Bootstrap入怀——导航栏篇
May 30 Javascript
浅谈JavaScript 覆盖原型以及更改原型
Aug 31 Javascript
js实现悬浮窗效果(支持拖动)
Mar 09 Javascript
详谈Angular 2+ 的表单(一)之模板驱动型表单
Apr 25 Javascript
Node.js利用断言模块assert进行单元测试的方法
Sep 28 Javascript
vue-devtools的安装和使用步骤详解
Oct 17 Javascript
element-ui 本地化使用教程详解
Oct 28 Javascript
完美解决vue 中多个echarts图表自适应的问题
Jul 19 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图片上传类带图片显示
2006/11/25 PHP
Laravel 中获取上一篇和下一篇数据
2015/07/27 PHP
PHP时间戳格式全部汇总 (获取时间、时间戳)
2016/06/13 PHP
使用phpQuery获取数组的实例
2017/03/13 PHP
PHP编译configure时常见错误的总结
2017/08/17 PHP
阿里云的WindowsServer2016上部署php+apache
2018/07/17 PHP
PHP+redis实现微博的推模型案例分析
2019/07/10 PHP
使用jquery与图片美化checkbox和radio控件的代码(打包下载)
2010/11/11 Javascript
一个关于javascript匿名函数的问题分析
2012/03/30 Javascript
ajax异步刷新实现更新数据库
2012/12/03 Javascript
JS实现简单的键盘打字的效果
2015/04/24 Javascript
分享9点个人认为比较重要的javascript 编程技巧
2015/04/27 Javascript
基于JavaScript的操作系统你听说过吗?
2016/01/28 Javascript
jquery事件绑定解绑机制源码解析
2016/09/19 Javascript
Bootstrap风格的WPF样式
2016/12/07 Javascript
JavaScript中的FileReader图片预览上传功能实现代码
2017/07/24 Javascript
iview给radio按钮组件加点击事件的实例
2017/09/30 Javascript
详解ES6中的代理模式——Proxy
2018/01/08 Javascript
详解vue-router 命名路由和命名视图
2018/06/01 Javascript
JS使用正则表达式获取小括号、中括号及花括号内容的方法示例
2018/06/01 Javascript
Vue3 响应式侦听与计算的实现
2020/11/11 Javascript
Python字符遍历的艺术
2008/09/06 Python
Python中用memcached来减少数据库查询次数的教程
2015/04/07 Python
python编写微信远程控制电脑的程序
2018/01/05 Python
python爬取足球直播吧五大联赛积分榜
2018/06/13 Python
Python检查ping终端的方法
2019/01/26 Python
深入浅析python 协程与go协程的区别
2019/05/09 Python
python 有效的括号的实现代码示例
2019/11/11 Python
Python+Redis实现布隆过滤器
2019/12/08 Python
Python Selenium破解滑块验证码最新版(GEETEST95%以上通过率)
2021/01/29 Python
Python中全局变量和局部变量的理解与区别
2021/02/07 Python
白岩松演讲
2014/05/21 职场文书
国庆节标语大全
2014/10/08 职场文书
超市采购员岗位职责
2015/04/07 职场文书
超级实用的公文标题大全!
2019/07/19 职场文书
《英雄联盟》2022日蚀、月蚀皮肤演示 黑潮亚索曝光
2022/04/13 其他游戏