javascript 延迟加载技术(lazyload)简单实现


Posted in Javascript onJanuary 17, 2011

1.前言

懒加载技术(简称lazyload)并不是新技术, 它是js程序员对网页性能优化的一种方案.lazyload的核心是按需加载.在大型网站中都有lazyload的身影,例如谷歌的图片搜索页,迅雷首页,淘宝网,QQ空间等.因此掌握lazyload技术是个不错的选择,可惜jquery插件lazy load官网(http://www.appelsiini.net/projects/lazyload)称不支持新版浏览器。

2.lazyload在什么场合中应用比较合适?

涉及到图片,falsh资源 , iframe, 网页编辑器(类似FCK)等占用较大带宽,且这些模块暂且不在浏览器可视区内,因此可以使用lazyload在适当的时候加载该类资源.避免网页打开时加载过多资源,让用户等待太久.

3.如何实现lazyload?

lazyload的难点在如何在适当的时候加载用户需要的资源(这里用户需要的资源指该资源呈现在浏览器可视区域)。因此我们需要知道几点信息来确定目标是否已呈现在客户区,其中包括:

1.可视区域相对于浏览器顶端位置

2.待加载资源相对于浏览器顶端位置.

在得到以上两点数据后,通过如下函数,便可得出某对象是否在浏览器可视区域了.

//返回浏览器的可视区域位置 

 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 = "d1" style = "width:50px; height:50px; background:red;position:absolute; top:1000px"> 

</div> 

 var d1 = document.getElementById("d1"); 

 window.onscroll = function(){ 

 
var prec1 = getClient(); 


var prec2 = getSubClient(d1); 


 if(intens(prec1,prec2)){ 

 

alert("true") 

   
} 

}

我们只需要在弹出窗口的地方加载我们需要的资源.

这里值得注意的是:目标对象呈现在客户区域时,会随着滚动而不断的弹出窗口.因此我们需要在弹出第一个窗口后取消对该区域的监测,这里用一个数组来收集需要监测的对象。还需要注意:因为onscroll事件和onresize事件都会改变游览器可视区域信息,因此在该类事件触发后需要重新计算目标对象是否在可视区域,这里用autocheck()函数实现.(迅雷首页的lazyload没有在onresize事件中重新计算目标对象是否在浏览器可视区域,因此如果先将浏览器窗口缩小到一定尺寸后滚动到需要加载图片的区域后点击最大化,图片加载不出来,呵呵,以后需要注意了).

增加元素:<div id = "d2" 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 学习笔记 选择器之三
Jul 23 Javascript
JS 实现BASE64_ENCODE和BASE64_DECODE(实例代码)
Nov 13 Javascript
php中给js数组赋值方法
Mar 10 Javascript
浅析JavaScript中作用域和作用域链
Dec 06 Javascript
深入学习Bootstrap表单
Dec 13 Javascript
微信小程序 数据封装,参数传值等经验分享
Jan 09 Javascript
Vue.js组件tab实现选项卡切换
Mar 23 Javascript
详解JS模块导入导出
Dec 20 Javascript
vue 动态修改a标签的样式的方法
Jan 18 Javascript
vue自定义移动端touch事件之点击、滑动、长按事件
Jul 10 Javascript
element日历calendar组件上月、今天、下月、日历块点击事件及模板源码
Jul 27 Javascript
vue判断按钮是否可以点击
Apr 09 Vue.js
关于COOKIE个数与大小的问题
Jan 17 #Javascript
js实现的跟随鼠标移动的时钟效果(中英文日期显示)
Jan 17 #Javascript
Jquery 插件开发笔记整理
Jan 17 #Javascript
JQuery学习笔记 nt-child的使用
Jan 17 #Javascript
Jquery知识点三 jquery表单对象操作
Jan 17 #Javascript
基于jquery的返回顶部效果(兼容IE6)
Jan 17 #Javascript
jquery+ajax每秒向后台发送请求数据然后返回页面的代码
Jan 17 #Javascript
You might like
我用php+mysql写的留言本
2006/10/09 PHP
php 应用程序安全防范技术研究
2009/09/25 PHP
php代码运行时间查看类代码分享
2011/08/06 PHP
通过curl模拟post和get方式提交的表单类
2014/04/23 PHP
php使用ereg验证文件上传的方法
2014/12/16 PHP
js预载入和JavaScript Image()对象使用介绍
2011/08/28 Javascript
IE中jquery.form中ajax提交没反应解决方法分享
2012/09/11 Javascript
两个listbox实现选项的添加删除和搜索
2013/03/01 Javascript
js综合应用实例简单的表格统计
2013/09/03 Javascript
javascript折半查找详解
2015/01/26 Javascript
JavaScript中的关联数组问题
2015/03/04 Javascript
js实现带有介绍的Select列表菜单实例
2015/08/18 Javascript
canvas绘制七巧板
2017/02/03 Javascript
使用Bootstrap打造特色进度条效果
2017/05/02 Javascript
Angular4绑定html内容出现警告的处理方法
2017/11/03 Javascript
javascript Function函数理解与实战
2017/12/01 Javascript
快速解决Vue项目在IE浏览器中显示空白的问题
2018/09/04 Javascript
mpvue小程序循环动画开启暂停的实现方法
2019/05/15 Javascript
微信小程序实现上传照片代码实例解析
2020/08/04 Javascript
[01:07:19]DOTA2-DPC中国联赛 正赛 CDEC vs XG BO3 第一场 1月19日
2021/03/11 DOTA
实践Python的爬虫框架Scrapy来抓取豆瓣电影TOP250
2016/01/20 Python
TensorFlow 实战之实现卷积神经网络的实例讲解
2018/02/26 Python
python实现停车管理系统
2018/11/30 Python
Python 虚拟空间的使用代码详解
2019/06/10 Python
django表单的Widgets使用详解
2019/07/22 Python
使用Python实现文字转语音并生成wav文件的例子
2019/08/08 Python
Python函数参数定义及传递方式解析
2020/06/10 Python
英国家用电器折扣网站:Electrical Discount UK
2018/09/17 全球购物
莫斯科高科技在线商店:KremlinStore
2019/03/13 全球购物
Linux操作面试题
2012/05/16 面试题
中学生获奖感言
2014/02/04 职场文书
出差报告格式模板
2014/11/06 职场文书
交通事故调解协议书
2015/05/20 职场文书
家长会主持词开场白
2015/05/29 职场文书
在 Golang 中实现 Cache::remember 方法详解
2021/03/30 Python
MYSQL主从数据库同步备份配置的方法
2021/05/26 MySQL