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自己写tab滑动门(通用版)
Oct 30 Javascript
JQuery操作tr和td内容的方法实例
Mar 06 Javascript
window.navigate 与 window.location.href 的使用区别介绍
Sep 21 Javascript
JavaScript+CSS控制打印格式示例介绍
Jan 07 Javascript
Javascript中的String对象详谈
Mar 03 Javascript
javascript实现状态栏文字首尾相接循环滚动的方法
Jul 22 Javascript
详解iframe与frame的区别
Jan 13 Javascript
AngularJS Bootstrap详细介绍及实例代码
Jul 28 Javascript
微信小程序购物商城系统开发系列-工具篇的介绍
Nov 21 Javascript
vue axios同步请求解决方案
Sep 29 Javascript
JavaScript时间戳与时间日期间相互转换
Dec 11 Javascript
JS性能优化实现方法及优点进行
Aug 30 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/10/09 PHP
PHP实现图片简单上传
2006/10/09 PHP
php 将字符串按大写字母分隔成字符串数组
2010/04/30 PHP
PHP检测字符串是否为UTF8编码的常用方法
2014/11/21 PHP
PHP中使用Imagick读取pdf并生成png缩略图实例
2015/01/21 PHP
分享五个PHP7性能优化提升技巧
2015/12/07 PHP
指定js可访问其它域名的cookie的方法
2007/09/18 Javascript
js操作二级联动实现代码
2010/07/27 Javascript
js获取触发事件元素在整个网页中的绝对坐标(示例代码)
2013/12/13 Javascript
JS方法调用括号的问题探讨
2014/01/24 Javascript
使用js实现数据格式化
2014/12/03 Javascript
IScroll5 中文API参数说明和调用方法
2016/05/21 Javascript
利用JS实现简单的瀑布流加载图片效果
2017/04/22 Javascript
基于vue2.0实现简单轮播图
2017/11/27 Javascript
轻松学习JavaScript函数中的 Rest 参数
2019/05/30 Javascript
JS实现小米轮播图
2020/09/21 Javascript
Python中的rfind()方法使用详解
2015/05/19 Python
Python聚类算法之基本K均值实例详解
2015/11/20 Python
python用reduce和map把字符串转为数字的方法
2016/12/19 Python
Django 实现下载文件功能的示例
2018/03/06 Python
python生成ppt的方法
2018/06/07 Python
Django页面数据的缓存与使用的具体方法
2019/04/23 Python
python binascii 进制转换实例
2019/06/12 Python
Python在Matplotlib图中显示中文字体的操作方法
2019/07/29 Python
python实现windows倒计时锁屏功能
2019/07/30 Python
python文字转语音的实例代码分析
2019/11/12 Python
Python气泡提示与标签的实现
2020/04/01 Python
python访问hdfs的操作
2020/06/06 Python
Python绘制词云图之可视化神器pyecharts的方法
2021/02/23 Python
HTML5 绘制图像(上)之:关于canvas元素引领下一代web页面的问题
2013/04/24 HTML / CSS
html5使用canvas实现跟随光标跳动的火焰效果
2014/01/07 HTML / CSS
Hotels.com印度:酒店预订
2019/05/11 全球购物
纪念建党演讲稿范文
2014/01/13 职场文书
学生鉴定评语大全
2014/05/05 职场文书
维护民族团结演讲稿
2014/08/27 职场文书
企业党员岗位承诺书
2015/04/27 职场文书