【分享】LazyLoad延迟加载(按需加载)

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:我的源码

 

ContractedBlock.gifExpandedBlockStart.gif代码
<!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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/261958.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

python中ipo模型有_python ipo模型是指什么?_后端开发

c语言中如何用do...while语句求1到100的累加和_后端开发 c语言中用do...while语句求1到100的累加和的方法是&#xff1a;1、首先定义变量i与sum&#xff0c;如【int sum0,i1】&#xff1b;2、然后用do...while语句实现即可&#xff0c;如【do{sumsumi;i;}while(i<100)】。py…

Storm 疑难杂症。

疑难解答&#xff1a;这个页面列出了一些人们在使用storm时遇到的问题和他们的解决方案。worker 进程 启动时没有堆栈信息。可能的情形&#xff1a;Topology 只在一台机器的不同worker中运行&#xff0c;但是在多节点上运行会遇到问题或崩溃。解决方法&#xff1a;你可能配置错…

第七章数组答案C语言,C语言复习题及答案-第七章-数组

.WORD版本第七章数组 (8学时)学习目的与要求&#xff1a;1 、重点掌握一维数组的定义和引用&#xff1b;2 、基本掌握二维数组的定义和引用&#xff1b;3 、重点掌握字符型数组的定义与引用&#xff1b;4 、能正确使用字符串处理函数&#xff1b;5 、学会使用数组解决实际问题。…

一些布局

嗯&#xff0c;今天重新玩了下布局&#xff0c;把部分布局方式整理了一下&#xff0c;也就顺手记了下来。&#xff08;都测试过了&#xff0c;IE6 ,FF,opera,chromer浏览器现在流行的版本都支持&#xff09; 一、三列&#xff08;固宽&#xff09; <div id"container&q…

英语26个字母使用频度

LetterLetter namePronunciation NLetterFrequency LetterFrequencyAa/ˈeɪ/, //[nb 2] 1A8.17% E12.70%Bbee/ˈbiː/ 2B1.49% T9.06%Ccee/ˈsiː/ 3C2.78% A8.17%Ddee/ˈdiː/ 4D4.25% O7.51%Ee/ˈiː/ 5E12.70% I6.97%Fef (eff as a verb)/ˈɛf/ 6F2.23% N6.75%Ggee/ˈdʒi…

java签到_实战:如果让你用SpringBoot实现签到奖励的功能,你会怎么做?

阅读本文大概需要 6 分钟。来自&#xff1a;网络前言最近在做社交业务&#xff0c;用户进入APP后有签到功能&#xff0c;签到成功后获取相应的奖励&#xff1a;项目状况&#xff1a;前期尝试业务阶段&#xff1b;特点&#xff1a;快速实现&#xff08;不需要做太重&#xff0c;…

c语言经典算法大全pdf,c语言经典算法100例pdf版.pdf

c语言经典算法100例pdf版C 语言经典算法 100 例C 语言编程经典 100 例A&#xff1a;【程序1】题目&#xff1a;有1、2、3、4 个数字&#xff0c;能组成多少个互不相同且无重复数字的三位数&#xff1f;都是多少&#xff1f;1.程序分析&#xff1a;可填在百位、十位、个位的数字…

软件开发工具介绍之 1.代码生成器

在程序开发过程当中&#xff0c;程序员会经常做着重复性的工作&#xff0c;最常见的是访问数据库&#xff0c;程序员要经常编写增、删、改、分页之类的操作。为了避免这个问题&#xff0c;节省大量机械录入的时间和重复劳动&#xff0c;提高工作效率&#xff0c;而将精力集中于…

python自带的shell、其性能优于ipython吗_Python自带的shell,其性能优于IPython

信源X的&#xff0c;自带每一机事件的都相等个随概率&#xff0c;即P。 优于 自带优于 自带求(机械的保养要。 优于标有机械的主管理要指。 下尺性期人手节分的病离急法整复后&#xff0c;自带项处做哪理&#xff1a;还应。 并放下肢射至&#xff0c;优于现右肢放扭伤右下臀及后…

虚拟机测试必备虚拟机之VirtualBox 使用

2019独角兽企业重金招聘Python工程师标准>>> 安装&#xff0c;windowns在官网上对应版本下载下一步安装结束即可&#xff0c;配置有seting可以选择中文&#xff0c;方便理解&#xff0c;其实英文也好功能 不多。 安装linux&#xff1a;ubuntu&#xff0c;如果有网su…

Android如何在测试程序中删除被测应用私有的原始数据

我们知道在Android App测试时&#xff0c;当我们想把应用程序恢复的初始状态&#xff0c;我们通常可以有以下几种做法&#xff1a; 手动 到Setting -> Apps -> 单击我们要测得应用程序 -> 选择Clear data 这样重新启动App的时候&#xff0c;我们的程序就处于初始状态了…

c语言结构体编程,[编程] C语言的结构体详解

结构体struct 结构体名{}变量名;结构体变量&#xff1a;struct person{char *name;int age;float score;} student;成员的获取和赋值//Members of the acquisition and assignmentstudent.name"taoshihan";student.age30;student.score100;printf("name%s \n&qu…

基于.NET Framework 4.0的解决方案部署

VS 2010发布之后&#xff0c;随着而来的框架版本也升级到了.NET Framework 4.0。我相信很多朋友已经在用了吧。这一篇文章总结了如何基于.NET Framework 4.0&#xff0c;进行解决方案部署。 之所以要单独写一下&#xff0c;是因为确实这个版本与之前的.NET Framework 2.0&#…

chrome网页自动化插件_chrome网页注释插件

问题背景&#xff1a;tensorflow中文官方文档无法做网页注释。原本使用Hypothesis - Web & PDF Annotationdiigo达到了500个注释的上限&#xff0c;继续做注释&#xff0c;每次注释均为弹出超过上限的提醒&#xff0c;影响学习。目前结论&#xff1a;Scrible Toolbarhttps:…

【BZOJ 3098】 Hash Killer II

Description 这天天气不错&#xff0c;hzhwcmhf神犇给VFleaKing出了一道题&#xff1a;给你一个长度为N的字符串S&#xff0c;求有多少个不同的长度为L的子串。子串的定义是S[l]、S[l 1]、... S[r]这样连续的一段。两个字符串被认为是不同的当且仅当某个位置上的字符不同。 VF…

如何在Windows Azure VM上的SQL Server和Windows Azure SQL Database两者中做出选择

作者信息&#xff1a;本篇文章是由SQL Server Cloud Infrastructure Team的 Madhan Arumugam 和 Guy Bowerman共同著作。 简介 把SQL 数据托管在哪里&#xff0c;Windows Azure 为您提供了两个选择&#xff0c;VM上的SQL Server&#xff08;以下简称 SQL/VM&#xff09;和 Wind…

MFC 控件布局

在MFC要自己控制控件随窗口变化而改变其大小 以下提供一个解决办法&#xff0c;easysize.h来自codeproject /Files/pbreak/EasySize.rar 第一:添加消息映射 afx_msg void OnSize(UINT nType, int cx, int cy); afx_msg void OnSizing(UINT fwSide, LPRECT pRect); ON_WM_SIZE()…

c语言离散卷积编程,实验一 离散卷积的C语言编程.ppt

实验一 离散卷积的C语言编程.ppt实验一 离散卷积的C语言编程实验 DSP实验室 实验性质 综合设计性实验 实验目的 1 了解和认识常用的各种信号&#xff1b; 2 掌握卷积的定义和计算方法&#xff1b; 3 掌握在计算机中生成以及绘制信号序列图的方法。 实验原理 离散时间系统中几种…

graphviz 画决策树_数据挖掘入门系列教程(四)之基于scikit-lean决策树处理Iris

数据挖掘入门系列教程&#xff08;四&#xff09;之基于scikit-lean决策树处理Iris加载数据集数据特征训练随机森林调参工程师结尾数据挖掘入门系列教程&#xff08;四&#xff09;之基于scikit-lean决策树处理Iris在上一篇博客&#xff0c;我们介绍了决策树的一些知识。如果对…

设计模式UML图

1.简单工厂模式 2.工厂模式 工厂模式与简单工厂模式的不同在于&#xff0c;每个操作类都有自己的工厂&#xff0c;而且把逻辑判断交给了客户端&#xff0c;而简单工厂的逻辑判断在工厂类里边&#xff0c;当增加新的操作类时&#xff0c;简单工厂需要修改工厂类&#xff0c;而工…