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 相关文章推荐
你所要知道JS(DHTML)中的一些技巧
Jan 09 Javascript
解析Javascript小括号“()”的多义性
Dec 03 Javascript
node.js中的定时器nextTick()和setImmediate()区别分析
Nov 26 Javascript
javascript框架设计之类工厂
Jun 23 Javascript
JavaScript+html5 canvas绘制的小人效果
Jan 27 Javascript
Bootstrap的modal拖动效果
Dec 25 Javascript
javascript 中事件冒泡和事件捕获机制的详解
Sep 01 Javascript
浅谈angular2路由预加载策略
Oct 04 Javascript
vue学习教程之带你一步步详细解析vue-cli
Dec 26 Javascript
Vue.JS实现垂直方向展开、收缩不定高度模块的JS组件
Jun 19 Javascript
vue devtools的安装与使用教程
Aug 08 Javascript
浅谈Three.js截图并下载的大坑
Nov 01 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检测文件编码的方法示例
2014/04/25 PHP
jQuery Mobile + PHP实现文件上传
2014/12/12 PHP
用php守护另一个php进程的例子
2015/02/13 PHP
PHP使用内置函数file_put_contents写入文件及追加内容的方法
2015/12/07 PHP
tp5框架前台无限极导航菜单类实现方法分析
2020/03/29 PHP
jquery插件之easing使用
2010/08/19 Javascript
c#和Javascript操作同一json对象的实现代码
2012/01/17 Javascript
jquery 跳到顶部和底部动画2句代码简单实现
2013/07/18 Javascript
jquery新的绑定事件机制on方法的使用方法
2014/04/15 Javascript
基于JS实现简单的样式切换效果代码
2015/09/04 Javascript
javascript汉字拼音互转的简单实例
2016/10/09 Javascript
angular和BootStrap3实现购物车功能
2017/01/25 Javascript
webstorm中配置nodejs环境及npm的实例
2018/05/15 NodeJs
基于vue实现可搜索下拉框定制组件
2020/03/26 Javascript
Element UI 自定义正则表达式验证方法
2018/09/04 Javascript
Echarts实现单条折线可拖拽效果
2019/12/19 Javascript
[04:07]显微镜下的DOTA2第八期——英雄复活动作
2014/06/24 DOTA
零基础写python爬虫之爬虫编写全记录
2014/11/06 Python
Python2.7读取PDF文件的方法示例
2017/07/13 Python
Python实现二维数组输出为图片
2018/04/03 Python
Python global全局变量函数详解
2018/09/18 Python
Ubuntu下Python+Flask分分钟搭建自己的服务器教程
2019/11/19 Python
Python基础教程(一)——Windows搭建开发Python开发环境
2020/07/20 Python
css3制作彩色边线3d立体按钮的示例(css3按钮)
2014/05/06 HTML / CSS
英国最大的手表网站:The Watch Hut
2017/03/31 全球购物
国家地理在线商店:Shop National Geographic
2018/06/30 全球购物
高级Java程序员面试题
2016/06/23 面试题
初中优秀班集体申报材料
2014/05/01 职场文书
主题班会演讲稿
2014/05/22 职场文书
工会工作先进事迹
2014/08/18 职场文书
2014国庆65周年领导讲话稿(3篇)
2014/09/21 职场文书
校园开放日新闻稿
2015/07/17 职场文书
婚礼双方父亲致辞
2015/07/27 职场文书
Python爬虫基础初探selenium
2021/05/31 Python
开机音效回归! Windows 11重新引入开机铃声
2021/11/21 数码科技
Redis实现订单过期删除的方法步骤
2022/06/05 Redis