1:实际需求

  大型网站往往很矛盾,想用户在首页看到更多东西,又不想浪费太多服务器流量。比如一个有3屏的首页。可能50%的用户进首页的目的是点击首页的连接,到子页面。

那么我们的网站却为100%的用户加载了 3个 屏幕的所有内容。如果可以按需加载内容。就可以节约更多资源,做更多好的应用。

2:解决方案

  用客户端语言来判断用户当前的可视范围,只加载用户可视范围的内容。最主要的是图片。因为文字信息,相对较小,其他多媒体内容相对占用服务器流量更多。

3:演示例子

4:解析

  首先我们要分析下,这个效果会有一个 最外面的容器。他包涵了里面需要延迟加载一些内容。容器一般可能是浏览器窗口本身(window),或者一个有滚动条的DIV。

OK,我们必须获取这个容器的一些参数。比如 可视宽度,可视高度,水平卷去宽度,垂直卷去高度。我使用下面的程序。

  4.1:获取容器对象属性

_this.docInfo=function(){//获取容器的相关信息
var d={},db= (wf)? document.body : warpper,
dd=(wf) ? document.documentElement : warpper;
if(sys.ie){
d.offh=dd.offsetHeight;//可视区域H
d.offw=dd.offsetWidth;//可视区域W
}else{
if(wf){
d.offw=window.innerWidth;//可视区域H
d.offh=window.innerHeight;//可视区域W
}else{
d.offh=dd.offsetHeight;//可视区域H
d.offw=dd.offsetWidth;//可视区域W
}
}
d.jtop=(wf) ? db.scrollTop+dd.scrollTop : db.scrollTop ;//垂直卷去高度
d.jleft=(wf) ? db.scrollLeft+dd.scrollLeft : db.scrollLeft;//水平卷去宽度
//被卷去的宽度 window 使用两个相加 div的卷曲就直接使用scrollLeft就OK
$j("bbb").innerHTML=d.offh+','+d.offw+','+d.jtop+','+d.jleft
return d;
}
//注意在非IE 浏览器下 获取非window对象的可视区域 使用offsetHeight 和 offsetWidth (跟IE 一样)
//在非IE 下获取 window对象的可视区域 则要使用 window.innerWidth 和window.innerHeight
//也就是说在非IE 下的 window 和 非window 对象的 可视区域获取是不一样的。

  4.2:获取加载内容的信息

    我们主要获取加载对象距离 页面容器对象的距离 。

IE 6 7会有个BUG

wtop=sys.ie ? (sys.ie[1]=='6.0' || sys.ie[1]=='7.0') ? 0 : warpper.offsetTop : warpper.offsetTop,
wleft=sys.ie ? (sys.ie[1]=='6.0' || sys.ie[1]=='7.0') ? 0 : warpper.offsetLeft : warpper.offsetLeft,
getoff=function(o){//获取IMG对象的 offw and offh

o.innerHTML=(o.offsetTop-wtop) +','+ (o.offsetLeft-wleft);
return (o.offsetTop-wtop) +','+ (o.offsetLeft-wleft);
//注意 o.offsetTop 在chrome下要等window.onload以后才能正确获取
};

  4.3:加载主程序

    他主要负责加载当前在可视范围内对象。那么我们必须去遍历所有要加载的对象。判断对象是否在当前的加载中。
然后加载他。我下面会有一个图。(方法可能不太好)

_this.Load=function(){
var hereline=[];
hereline[1]=doc.offh+doc.jtop;
hereline[2]=doc.offw+doc.jleft;

for(i=0;i<imgs.length;i++){

if(imgs[i][1] != undefined){//判断当前对象是否已经加载过
var jj=hereline[1] - imgs[i][1] < doc.offh +130 && hereline[1] - imgs[i][1] > 0 ? true : false,
jjj=hereline[2] - imgs[i][2] < doc.offw +270 && hereline[2] - imgs[i][2] > 0 ? true : false;
if(jj && jjj){
imgall[i].innerHTML+='第'+(++j)+'个加载';
imgs[i][1]=undefined;
}
}

}

if( j >= imgs.length){//判断是否已经全部加载完毕
//取消时间绑定
alert("已经全部加载完成,程序将不再执行")
warpper.onscroll=null;
warpper.onresize=null;
}
}

我不太喜欢我的判断程序,但是暂时没找到,或者我没理解更好的算法。所以就先用这个了。

大体的意思:用容器的可视高度+容器滚动高度 - 对象距离距离容器距离 > 容器可视 + 对象本身高或宽 就证明在加载范围。(绕口令)

我们还必须把 已经加载过的对象排除在外。因为加载过的对象也满足以上公式,同时也可以少判断一些。

imgs[i][1]=undefined;

if(imgs[i][1] != undefined){//判断当前对象是否已经加载过

  特别注意(看图)

看上图 A B C D。 分别有4个不同的角露在了 可视范围内。所以这4个对象是需要加载的。

如果只考虑对象的某个点,或者某个线来判断对象是否在可视范围,可能带来不好的体验。

由于有上面这种情况,也给我们的编程(判断是否在可视范围内)增加了难度。

我上面的方法,是可以完成了。(如果有发现BUG ,请给我指点。其实我也有点晕了。)

最后还有几个技巧,比如

  1:对象全部加载完了。就应该去掉容器对象事件触发。

  2:尽量优化判断对象是否在可视范围,或者遍历的对象的算法。可以节约很多浏览器资源。

  3:cloudgamer 还提到一个 延迟触发,就是快速的滑动滚动条,延迟一下也是一个小的优化。

5:推荐文章

  cloudgamer  的 他讲的很详细,也比我做的要好。所以推荐去学习他的这个效果哦。很多东西我也借鉴他的。

还有就是感谢他的指点。Lazyload 延迟加载效果

6:我的源码

代码

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>lazyload</title>

</head>

<body>
<style type="text/css">
body{ margin:0px; padding:0; font-size:12px;}
.jelle_box{width:270px; height:129px; border:1px solid #CCC; float:left;}
</style>
<input type="button" value="重新开始" onclick="lazyload().judge();" />
<div style="width:100%; height:500px; overflow:scroll; border:2px solid #999;" id="jelle_abcd">
<div id="aaa" style="width:2500px; height:800px; margin:10px;">
<div class="jelle_box"></div>
<div class="jelle_box"></div>
<div class="jelle_box"></div>
<div class="jelle_box"></div>
<div class="jelle_box"></div>
<div class="jelle_box"></div>
<div class="jelle_box"></div>
<div class="jelle_box"></div>
<div class="jelle_box"></div>
<div class="jelle_box"></div>
<div class="jelle_box"></div>
<div class="jelle_box"></div>
<div class="jelle_box"></div>
<div class="jelle_box"></div>
<div class="jelle_box"></div>
<div class="jelle_box"></div>
<div class="jelle_box"></div>
<div class="jelle_box"></div>
<div class="jelle_box"></div>
<div class="jelle_box"></div>
<div class="jelle_box"></div>
<div class="jelle_box"></div>
<div class="jelle_box"></div>
<div class="jelle_box"></div>
<div class="jelle_box"></div>
<div class="jelle_box"></div>
<div class="jelle_box"></div>
<div class="jelle_box"></div>
<div class="jelle_box"></div>
<div class="jelle_box"></div>
<div class="jelle_box"></div>
<div class="jelle_box"></div>
<div class="jelle_box"></div>
<div class="jelle_box"></div>
<div class="jelle_box"></div>
<div class="jelle_box"></div>
<div class="jelle_box"></div>
<div class="jelle_box"></div>
<div class="jelle_box"></div>
<div class="jelle_box"></div>
<div class="jelle_box"></div>
<div class="jelle_box"></div>
<div class="jelle_box"></div>
<div class="jelle_box"></div>
<div class="jelle_box"></div>
<div class="jelle_box"></div>
<div class="jelle_box"></div>
<div class="jelle_box"></div>
<div class="jelle_box"></div>
</div>
</div>
<div style=" height:30px" id="bbb"></div>
<script type="text/javascript">
(function(){
window.lazyload=function(){
var _this={},//方法集合
imgsurl=['baidu_logo_2.gif']//最开始是用来加载图片的。这里是需要加载图片的地址集合
imgs=[],//全部IMG 数据 格式为 [[url,offw,offh],[url,offw,offh]]
i=0,//循环变量
j=0,//判断当前的加载个数
warpper=document.getElementById('jelle_abcd'),//window,//容器对象
wf=(warpper==window) ? true : false;
doc={offw:0,offh:0,jtop:0,jleft:0},//包含一些 容器对象当前的一些属性
sys=(function(){//不必紧张这只是一个判断浏览器的函数,你可以使用很多方法来判断浏览器
var ua=navigator.userAgent.toLowerCase(),sys={};
sys.firefox=ua.match(/firefox\/([\d\.]+)/);
sys.ie=ua.match(/msie\s([\d\.]+)/);
sys.chrome=ua.match(/chrome\/([\d\.]+)/);
return sys;
})(),
$j=function(id){return document.getElementById(id);},
imgall=$j('aaa').getElementsByTagName('DIV'),
getoff=function(o){//获取IMG对象的 offw and offh
//alert(o.width)
o.innerHTML=(o.offsetTop-warpper.offsetTop) +','+ (o.offsetLeft-warpper.offsetLeft);
return (o.offsetTop-warpper.offsetTop) +','+ (o.offsetLeft-warpper.offsetLeft);
//注意 o.offsetTop 在chrome下要等window.onload以后才能正确获取
};
//o.offsetTop获取对象距离浏览器顶部的距离 必须减去外面容器的距离浏览器的距离。(如果使用window容器就不用了)

(function(){//初始化容器对象绑定事件==
if(wf){
window.onscroll=function(){_this.judge();};
window.onresize=function(){_this.judge();};
}else{
warpper.onscroll=function(){_this.judge();}
warpper.onresize=function(){_this.judge();}
}
window.onload=function(){setTimeout(_this.judge,500);};
})()
//容器对象设置结束

for( i ; i<imgall.length ; i++ ){//初始化imgs 数组
var arr=[],off;
off=getoff(imgall[i]);
//alert(off)
arr.push(imgsurl[0]);
arr.push((off.split(',')[0]));
arr.push((off.split(',')[1]));
imgs.push(arr);
}

_this.Load=function(){
var hereline=[];
hereline[1]=doc.offh+doc.jtop;
hereline[2]=doc.offw+doc.jleft;

for(i=0;i<imgs.length;i++){

if(imgs[i][1] != undefined){//判断当前对象是否已经加载过
var jj=hereline[1] - imgs[i][1] < doc.offh +130 && hereline[1] - imgs[i][1] > 0 ? true : false,
jjj=hereline[2] - imgs[i][2] < doc.offw +270 && hereline[2] - imgs[i][2] > 0 ? true : false;
if(jj && jjj){
imgall[i].innerHTML+='第'+(++j)+'个加载';
imgs[i][1]=undefined;
}
}

}

if( j >= imgs.length){//判断是否已经全部加载完毕
//取消时间绑定
alert("已经全部加载完成,程序将不再执行")
warpper.onscroll=null;
warpper.onresize=null;
}
}

_this.docInfo=function(){//获取容器的相关信息
var d={},db= (wf)? document.body : warpper,
dd=(wf) ? document.documentElement : warpper;
if(sys.ie){
d.offh=dd.offsetHeight;//可视区域H
d.offw=dd.offsetWidth;//可视区域W
}else{
if(wf){
d.offw=window.innerWidth;//可视区域H
d.offh=window.innerHeight;//可视区域W
}else{
d.offh=dd.offsetHeight;//可视区域H
d.offw=dd.offsetWidth;//可视区域W
}
}
d.jtop=(wf) ? db.scrollTop+dd.scrollTop : db.scrollTop ;//垂直卷去高度
d.jleft=(wf) ? db.scrollLeft+dd.scrollLeft : db.scrollLeft;//水平卷去宽度
//被卷去的宽度 window 使用两个相加 div的卷曲就直接使用scrollLeft就OK
$j("bbb").innerHTML=d.offh+','+d.offw+','+d.jtop+','+d.jleft
return d;
}
//注意在非IE 浏览器下 获取非window对象的可视区域 使用offsetHeight 和 offsetWidth (跟IE 一样)
//在非IE 下获取 window对象的可视区域 则要使用 window.innerWidth 和window.innerHeight
//也就是说在非IE 下的 window 和 非window 对象的 可视区域获取是不一样的。

_this.judge=function(){//后来发现不用判断方向了
var d=_this.docInfo();
if( d.jtop != doc.jtop || d.jleft != doc.jleft || d.offw > doc.offw || d.offh > doc.offh){
//判断是否需要执行加载
//条件为 被卷去的 y x 变化 或者 窗口大小 发生变化触发
doc.jtop = d.jtop;
doc.offh = d.offh;
doc.jleft = d.jleft;
doc.offw = d.offw;
_this.Load();//加载程序
}
}
//setTimeout(_this.judge,500);//执行初始化加载
//setTimeout 防止onload 和 onscroll的重复执行
//也就是本来就有onscroll的时候 最先执行了onload
return _this;

}

})()
lazyload();
</script>

</body>
</html>

转载于:https://www.cnblogs.com/idche/archive/2010/05/27/lazyload.html

【分享】LazyLoad延迟加载(按需加载)相关推荐

  1. .NET中的按需加载/延迟加载 LazyT

    业务场景: 在项目开发中,经常会遇到特定的对象使用的加载问题,有的实例对象我们创建之后并非需要使用,只是根据业务场景来调用,所以可能会导致很多无效的实例加载 延迟初始化出现于.NET 4.0,主要用于 ...

  2. Webpack实战(九):实现资源按需加载-资源异步加载

    第八篇[<教你搞懂webpack如果实现代码分片(code splitting)>] (https://blog.csdn.net/lfcss/article/details/104099 ...

  3. webpack2+angular2 按需加载,优化首屏速度

    1.Angular2的按需加载及延迟加载 1.1 根模块AppModule 假设按需加载的模块为LazyModule,首页模块为LoginModule,根模块为AppModule.首先在AppModu ...

  4. 前端性能优化之jQuery按需加载轮播图

    引言 关于幻灯轮播图,想必大家都不陌生,尤其是基于 jQuery 的,插件.代码网上一搜一大堆,但是真正符合自己需求的几乎没有,所以我要打造一个符合自身需求,经得起广大网民考验的 jQuery 轮播图 ...

  5. ant design pro取消登录_JeecgBoot实战按需加载 Ant-Design-Vue和Icon

    一.Ant-Design-Vue 按需加载 1.创建js文件 src/components/lazy_antd.js import Vue from 'vue'// base library impo ...

  6. ionic入门教程第十六课-在微信中使用ionic的解决方案(按需加载加强版)

    对于微信端来说,其实使用ionic是一个比较大的前端框架. 有更多比较轻量化的前端框架可以选择. 但是使用ionic有一个明显的优点就是,能够做到一端开发,三端同步上线. 这个梗说了好多遍了,但确实是 ...

  7. React单页如何规划路由、设计Store、划分模块、按需加载

    本项目地址:react-coat-helloworld react-coat 同时支持浏览器渲染(SPA)和服务器渲染(SSR),本 Demo 仅演示浏览器渲染,请先了解一下:react-coat 第 ...

  8. Ant-Design-Vue和Icon按需加载方案 - JeecgBoot实战

    JeecgBoot实战 - 按需加载方案 文章目录 JeecgBoot实战 - 按需加载方案 一.Ant-Design-Vue 按需加载 二.Icon按需加载 一.Ant-Design-Vue 按需加 ...

  9. Vue性能优化:图片与组件,如何实现按需加载?

    Vue性能优化:图片与组件,如何实现按需加载? 前沿:按需加载是性能优化其中的一个环节,可以是图片的按需加载,也就是lazyload来实现按需加载的场景,也可以是组件库的引入,只需部分组件的使用而无需 ...

最新文章

  1. Grails 1.2参考文档速读(15):验证
  2. 浅析网站地图设置对网站的作用有哪些?
  3. CTFshow 信息收集 web17
  4. 你确定你真的喜欢编程吗??
  5. Android之打开手机系统相册
  6. 【平衡规划】Arithmetic Operations(CF1654E)
  7. [html] Ajax与Flash的优缺点分别是什么?
  8. php下载当前页面,php实现当前页面点击下载文件的简单方法
  9. 分布式事务之TCC服务设计和实现注意事项!
  10. WCF分布式开发步步为赢(14):WCF安全编程--基本概念
  11. 解码器输出PSNR为0表示什么
  12. 机器学习/深度学习常用库的配置及其适用的算法总结
  13. c语言平方根求和用sqrt函数,sqrt函数 Excel怎么使用平方根函数SQRT
  14. 【Win7快速清理痕迹】
  15. 派对屋3000效果器怎样调试_演出效果器的调试和使用技巧
  16. RxSwift取消定时
  17. USB to TTL python 本地测试串口通信
  18. Altera FPGA 远程更新
  19. 计算机硬盘密码解不开,Win10打不开磁盘显示需要输入48位恢复密钥以解锁此驱动器怎么办...
  20. Javascript语义分析器,教你如何实现Jquery库

热门文章

  1. 『数据库』无聊到爆炸的数据库文章--数据库的安全性
  2. 2种IO并发开发中的设计模式:Reactor and Proactor
  3. 迁移学习 nlp_NLP的发展-第3部分-使用ULMFit进行迁移学习
  4. 机器学习算法机器人足球_购买足球队:一种机器学习方法
  5. linux应用开发:用户空间如何通过sysfs控制GPIO
  6. Cloudstreams: 云间整合的下一个挑战
  7. 额尔古纳的俄罗斯女孩
  8. 解决GetManifestResourceNames()无法读取资源文件
  9. 神舟笔记本电源管理软件_笔记本电脑是一直插着电源好,还是拔了电源好?
  10. cpu开机就是60℃_铅锤哥:十五种电脑开机黑屏的原因与解决思路