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 源码分析笔记(3) Deferred机制
Jun 19 Javascript
100个不能错过的实用JS自定义函数
Mar 05 Javascript
JavaScript奇技淫巧44招【实用】
Dec 11 Javascript
jQuery复合事件结合toggle()方法的用法示例
Jun 10 jQuery
浅谈mint-ui 填坑之路
Nov 06 Javascript
vue+springboot实现项目的CORS跨域请求
Sep 05 Javascript
Vue filter格式化时间戳时间成标准日期格式的方法
Sep 16 Javascript
微信小程序自定义tabBar组件开发详解
Sep 24 Javascript
vue实现的微信机器人聊天功能案例【附源码下载】
Feb 18 Javascript
node将geojson转shp返回给前端的实现方法
May 29 Javascript
nodemon实现Typescript项目热更新的示例代码
Nov 19 Javascript
Ajax实现异步加载数据
Nov 17 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获取文件后缀名的三个函数
2012/10/15 PHP
php使用PDO执行SQL语句的方法分析
2017/02/16 PHP
Django 标签筛选的实现代码(一对多、多对多)
2018/09/05 PHP
php+jQuery ajax实现的实时刷新显示数据功能示例
2019/09/12 PHP
JS增加行复制行删除行的实现代码
2013/11/09 Javascript
再谈javascript原型继承
2014/11/10 Javascript
jquery预加载图片的方法
2015/05/27 Javascript
使用Object.defineProperty实现简单的js双向绑定
2016/04/15 Javascript
vue.js学习之递归组件
2016/12/13 Javascript
JavaScript Uploadify文件上传实例
2017/02/28 Javascript
ES6的解构赋值实例详解
2019/05/06 Javascript
微信小程序实现动态列表项的顺序加载动画
2019/07/25 Javascript
浅谈TypeScript的类型保护机制
2020/02/23 Javascript
Element-ui树形控件el-tree自定义增删改和局部刷新及懒加载操作
2020/08/31 Javascript
python计算最小优先级队列代码分享
2013/12/18 Python
教你如何在Django 1.6中正确使用 Signal
2014/06/22 Python
Python中使用第三方库xlutils来追加写入Excel文件示例
2015/04/05 Python
Python使用win32 COM实现Excel的写入与保存功能示例
2018/05/03 Python
Python 中包/模块的 `import` 操作代码
2019/04/22 Python
python3人脸识别的两种方法
2019/04/25 Python
使用Python实现毫秒级抢单功能
2019/06/06 Python
利用Python复制文件的9种方法总结
2019/09/02 Python
Python使用Pandas读写Excel实例解析
2019/11/19 Python
面向新手解析python Beautiful Soup基本用法
2020/07/11 Python
超级实用的8个Python列表技巧
2020/08/24 Python
linux centos 7.x 安装 python3.x 替换 python2.x的过程解析
2020/12/14 Python
华纳兄弟工作室的官方授权商店:WB Shop
2018/11/30 全球购物
美国帽子俱乐部商店:Hat Club
2019/07/05 全球购物
linux系统都有哪些运行级别
2016/03/26 面试题
教学质量评估实施方案
2014/03/17 职场文书
尊老爱亲美德少年事迹材料
2014/08/14 职场文书
就业协议书样本
2014/08/20 职场文书
中考学习决心书
2015/02/04 职场文书
虎兄虎弟观后感
2015/06/12 职场文书
运动会广播稿20字
2015/08/19 职场文书
SpringBoot SpringEL表达式的使用
2021/07/25 Java/Android