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 相关文章推荐
Dom加载让图片加载完再执行的脚本代码
May 15 Javascript
FF火狐下获取一个元素同类型的相邻元素实现代码
Dec 15 Javascript
jQuery 获取/设置/删除DOM元素的属性以a元素为例
May 23 Javascript
easyui validatebox验证
Apr 29 Javascript
JavaScript判断用户名和密码不能为空的实现代码
May 16 Javascript
JavaScript基础语法之js表达式
Jun 07 Javascript
JavaScript实现的微信二维码图片生成器的示例
Oct 26 Javascript
vue编译打包本地查看index文件的方法
Feb 23 Javascript
vue.js打包之后可能会遇到的坑!
Jun 03 Javascript
node获取客户端ip功能简单示例
Aug 24 Javascript
微信小程序保存图片到相册权限设置
Apr 09 Javascript
小程序实现密码输入框
Nov 16 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
德生9700DX电路分析
2021/03/02 无线电
php实现mysql封装类示例
2014/05/07 PHP
php使用curl获取https请求的方法
2015/02/11 PHP
php获取字符串中各个字符出现次数的方法
2015/02/23 PHP
PHP操作MySQL中BLOB字段的方法示例【存储文本与图片】
2017/09/15 PHP
laravel 输出最后执行sql 附:whereIn的使用方法
2019/10/10 PHP
JavaScript 实现完美兼容多浏览器的复制功能代码
2015/04/28 Javascript
学习JavaScript设计模式之策略模式
2016/01/12 Javascript
jQuery添加删除DOM元素方法详解
2016/01/18 Javascript
js与applet相互调用的方法
2016/06/22 Javascript
javascript cookie用法基础教程(概念,设置,读取及删除)
2016/09/20 Javascript
Bootstarp 基础教程之表单部分实例代码
2017/02/03 Javascript
微信小程序 弹窗自定义实例代码
2017/03/08 Javascript
Angular实现点击按钮后在上方显示输入内容的方法
2017/12/27 Javascript
jQuery实现的点击标题文字切换字体效果示例【测试可用】
2018/04/26 jQuery
详解Vue中watch的高级用法
2018/05/02 Javascript
jQuery实现的页面详情展开收起功能示例
2018/06/11 jQuery
Vue三种常用传值示例(父传子、子传父、非父子)
2018/07/24 Javascript
vue 解决setTimeOut和setInterval函数无效报错的问题
2020/07/30 Javascript
Python基于SMTP协议实现发送邮件功能详解
2018/08/14 Python
python-pyinstaller、打包后获取路径的实例
2019/06/10 Python
使用Pytorch来拟合函数方式
2020/01/14 Python
详解numpy1.19.4与python3.9版本冲突解决
2020/12/15 Python
使用Html5中的cavas画一面国旗
2019/09/25 HTML / CSS
微信小程序canvas实现水平、垂直居中效果
2020/02/05 HTML / CSS
ALLSAINTS英国官网:伦敦新锐潮流品牌
2016/09/19 全球购物
Max&Co官网:意大利年轻女性时尚品牌
2017/05/16 全球购物
日本整理专家Marie Kondo的官方在线商店:KonMari
2020/06/29 全球购物
小学少先队活动方案
2014/02/18 职场文书
春节晚会主持词
2014/03/24 职场文书
给公司的建议书范文
2014/05/13 职场文书
2014年全国法制宣传日宣传活动方案
2014/11/02 职场文书
吴仁宝观后感
2015/06/09 职场文书
庆七一活动简报
2015/07/20 职场文书
golang日志包logger的用法详解
2021/05/05 Golang
pytorch常用数据类型所占字节数对照表一览
2021/05/17 Python