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 相关文章推荐
如何让动态插入的javascript脚本代码跑起来。
Jan 09 Javascript
Jquery异步提交表单代码分享
Mar 26 Javascript
jquery简单实现网页层的展开与收缩效果
Aug 07 Javascript
jquery ajax后台返回list,前台用jquery遍历list的实现
Oct 30 Javascript
原生JS实现跑马灯效果
Feb 20 Javascript
详解vue 模拟后台数据(加载本地json文件)调试
Aug 25 Javascript
使用vue与jquery实时监听用户输入状态的操作代码
Sep 19 jQuery
使用webpack构建应用的方法步骤
Mar 04 Javascript
详解关于webpack多入口热加载很慢的原因
Apr 24 Javascript
Vue项目从webpack3.x升级webpack4不完全指南
Apr 28 Javascript
微信小程序防止多次点击跳转和防止表单组件输入内容多次验证功能(函数防抖)
Sep 19 Javascript
深入了解Vue动态组件和异步组件
Jan 26 Vue.js
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
ecshop 批量上传(加入自定义属性)
2012/03/20 PHP
基于PHP开发中的安全防范知识详解
2013/06/06 PHP
ThinkPHP的截取字符串函数无法显示省略号的解决方法
2014/06/25 PHP
ThinkPHP防止重复提交表单的方法实例分析
2018/05/10 PHP
可简单避免的三个JS发布错误的详细介绍
2013/08/02 Javascript
Javascript设置对象的ReadOnly属性(示例代码)
2013/12/25 Javascript
jquery根据属性和index来查找属性值并操作
2014/07/25 Javascript
分享33个jQuery与CSS3实现的绚丽鼠标悬停效果
2014/12/15 Javascript
简述AngularJS相关的一些编程思想
2015/06/23 Javascript
实例代码讲解jquery easyui动态tab页
2015/11/17 Javascript
AngularJs Dependency Injection(DI,依赖注入)
2016/09/02 Javascript
关于微信jssdk实现多图片上传的一点心得分享
2016/12/13 Javascript
深入理解AngularJs-scope的脏检查(一)
2017/06/19 Javascript
浅谈Vuex@2.3.0 中的 state 支持函数申明
2017/11/22 Javascript
详解使用vue-admin-template的优化历程
2018/05/20 Javascript
Openlayers实现距离面积测量
2020/09/28 Javascript
[01:10:27]DOTA2-DPC中国联赛正赛 SAG vs XG BO3 第二场 3月5日
2021/03/11 DOTA
python实现百度关键词排名查询
2014/03/30 Python
Python装饰器基础概念与用法详解
2018/12/22 Python
使用GitHub和Python实现持续部署的方法
2019/05/09 Python
python模块常用用法实例详解
2019/10/17 Python
Python字符串split及rsplit方法原理详解
2020/06/29 Python
python语言实现贪吃蛇游戏
2020/11/13 Python
extern是什么意思
2016/03/10 面试题
专科文秘应届生求职信
2013/11/18 职场文书
专科应届生求职信
2013/11/24 职场文书
网站开发实习生的自我评价
2013/12/11 职场文书
利群广告词
2014/03/20 职场文书
论文评语大全
2014/04/29 职场文书
2014年教师节演讲稿范文
2014/09/10 职场文书
2014年民主评议党员个人总结
2014/09/24 职场文书
2015年世界环境日活动总结
2015/02/11 职场文书
单位计划生育责任书
2015/05/09 职场文书
七年级作文之游记
2019/12/11 职场文书
Spark SQL 2.4.8 操作 Dataframe的两种方式
2021/10/16 SQL Server
Python 的 sum() Pythonic 的求和方法详细
2021/10/16 Python