0

0

LazyLoad 延迟加载(按需加载)_javascript技巧

php中文网

php中文网

发布时间:2016-05-16 18:26:08

|

1287人浏览过

|

来源于php中文网

原创

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

Anybot
Anybot

创建AI驱动的聊天机器人,快速、轻松地实现业务自动化

下载
复制代码 代码如下:

_this.Load=function(){
var hereline=[];
hereline[1]=doc.offh+doc.jtop;
hereline[2]=doc.offw+doc.jleft;
for(i=0;iLazyLoad 延迟加载(按需加载)_javascript技巧if(imgs[i][1] != undefined){//判断当前对象是否已经加载过
var jj=hereline[1] - imgs[i][1] 0 ? true : false,
jjj=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){//判断当前对象是否已经加载过
  特别注意(看图)
LazyLoad 延迟加载(按需加载)_javascript技巧
看上图 A B C D。 分别有4个不同的角露在了 可视范围内。所以这4个对象是需要加载的。

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

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

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



最后还有几个技巧,比如

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

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

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

5:推荐文章

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

还有就是感谢他的指点。 Lazyload 延迟加载效果
6:我的源码

复制代码 代码如下:





lazyload


























































<script type="text/javascript"> <br>(function(){ <br>window.lazyload=function(){ <br>var _this={},//方法集合 <br>imgsurl=['baidu_logo_2.gif']//最开始是用来加载图片的。这里是需要加载图片的地址集合 <br>imgs=[],//全部IMG 数据 格式为 [[url,offw,offh],[url,offw,offh]] <br>i=0,//循环变量 <br>j=0,//判断当前的加载个数 <br>warpper=document.getElementById('jelle_abcd'),//window,//容器对象 <br>wf=(warpper==window) ? true : false; <br>doc={offw:0,offh:0,jtop:0,jleft:0},//包含一些 容器对象当前的一些属性 <br>sys=(function(){//不必紧张这只是一个判断浏览器的函数,你可以使用很多方法来判断浏览器 <br>var ua=navigator.userAgent.toLowerCase(),sys={}; <br>sys.firefox=ua.match(/firefox\/([\d\.]+)/); <br>sys.ie=ua.match(/msie\s([\d\.]+)/); <br>sys.chrome=ua.match(/chrome\/([\d\.]+)/); <br>return sys; <br>})(), <br>$j=function(id){return document.getElementById(id);}, <br>imgall=$j('aaa').getElementsByTagName('DIV'), <br>getoff=function(o){//获取IMG对象的 offw and offh <br>//alert(o.width) <br>o.innerHTML=(o.offsetTop-warpper.offsetTop) +','+ (o.offsetLeft-warpper.offsetLeft); <br>return (o.offsetTop-warpper.offsetTop) +','+ (o.offsetLeft-warpper.offsetLeft); <br>//注意 o.offsetTop 在chrome下要等window.onload以后才能正确获取 <br>}; <br>//o.offsetTop获取对象距离浏览器顶部的距离 必须减去外面容器的距离浏览器的距离。(如果使用window容器就不用了) <br>(function(){//初始化容器对象绑定事件== <br>if(wf){ <br>window.onscroll=function(){_this.judge();}; <br>window.onresize=function(){_this.judge();}; <br>}else{ <br>warpper.onscroll=function(){_this.judge();} <br>warpper.onresize=function(){_this.judge();} <br>} <br>window.onload=function(){setTimeout(_this.judge,500);}; <br>})() <br>//容器对象设置结束 <br>for( i ; i<img all.length ; i++ ){//初始化imgs 数组 <br alt="LazyLoad 延迟加载(按需加载)_javascript技巧" >var arr=[],off; <br>off=getoff(imgall[i]); <br>//alert(off) <br>arr.push(imgsurl[0]); <br>arr.push((off.split(',')[0])); <br>arr.push((off.split(',')[1])); <br>imgs.push(arr); <br>} <br>_this.Load=function(){ <br>var hereline=[]; <br>hereline[1]=doc.offh+doc.jtop; <br>hereline[2]=doc.offw+doc.jleft; <br>for(i=0;i<img s.length;i++){ <br alt="LazyLoad 延迟加载(按需加载)_javascript技巧" >if(imgs[i][1] != undefined){//判断当前对象是否已经加载过 <br>var jj=hereline[1] - imgs[i][1] < doc.offh +130 && hereline[1] - imgs[i][1] > 0 ? true : false, <br>jjj=hereline[2] - imgs[i][2] < doc.offw +270 && hereline[2] - imgs[i][2] > 0 ? true : false; <br>if(jj && jjj){ <br>imgall[i].innerHTML+='第'+(++j)+'个加载'; <br>imgs[i][1]=undefined; <br>} <br>} <br>} <br>if( j >= imgs.length){//判断是否已经全部加载完毕 <br>//取消时间绑定 <br>alert("已经全部加载完成,程序将不再执行") <br>warpper.onscroll=null; <br>warpper.onresize=null; <br>} <br>} <br>_this.docInfo=function(){//获取容器的相关信息 <br>var d={},db= (wf)? document.body : warpper, <br>dd=(wf) ? document.documentElement : warpper; <br>if(sys.ie){ <br>d.offh=dd.offsetHeight;//可视区域H <br>d.offw=dd.offsetWidth;//可视区域W <br>}else{ <br>if(wf){ <br>d.offw=window.innerWidth;//可视区域H <br>d.offh=window.innerHeight;//可视区域W <br>}else{ <br>d.offh=dd.offsetHeight;//可视区域H <br>d.offw=dd.offsetWidth;//可视区域W <br>} <br>} <br>d.jtop=(wf) ? db.scrollTop+dd.scrollTop : db.scrollTop ;//垂直卷去高度 <br>d.jleft=(wf) ? db.scrollLeft+dd.scrollLeft : db.scrollLeft;//水平卷去宽度 <br>//被卷去的宽度 window 使用两个相加 div的卷曲就直接使用scrollLeft就OK <br>$j("bbb").innerHTML=d.offh+','+d.offw+','+d.jtop+','+d.jleft <br>return d; <br>} <br>//注意在非IE 浏览器下 获取非window对象的可视区域 使用offsetHeight 和 offsetWidth (跟IE 一样) <br>//在非IE 下获取 window对象的可视区域 则要使用 window.innerWidth 和window.innerHeight <br>//也就是说在非IE 下的 window 和 非window 对象的 可视区域获取是不一样的。 <br>_this.judge=function(){//后来发现不用判断方向了 <br>var d=_this.docInfo(); <br>if( d.jtop != doc.jtop || d.jleft != doc.jleft || d.offw > doc.offw || d.offh > doc.offh){ <br>//判断是否需要执行加载 <br>//条件为 被卷去的 y x 变化 或者 窗口大小 发生变化触发 <br>doc.jtop = d.jtop; <br>doc.offh = d.offh; <br>doc.jleft = d.jleft; <br>doc.offw = d.offw; <br>_this.Load();//加载程序 <br>} <br>} <br>//setTimeout(_this.judge,500);//执行初始化加载 <br>//setTimeout 防止onload 和 onscroll的重复执行 <br>//也就是本来就有onscroll的时候 最先执行了onload <br>return _this; <br>} <br>})() <br>lazyload(); <br></script>


相关文章

java速学教程(入门到精通)
java速学教程(入门到精通)

java怎么学习?java怎么入门?java在哪学?java怎么学才快?不用担心,这里为大家提供了java速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

相关标签:

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
Golang 并发编程模型与工程实践:从语言特性到系统性能
Golang 并发编程模型与工程实践:从语言特性到系统性能

本专题系统讲解 Golang 并发编程模型,从语言级特性出发,深入理解 goroutine、channel 与调度机制。结合工程实践,分析并发设计模式、性能瓶颈与资源控制策略,帮助将并发能力有效转化为稳定、可扩展的系统性能优势。

2

2026.02.27

Golang 高级特性与最佳实践:提升代码艺术
Golang 高级特性与最佳实践:提升代码艺术

本专题深入剖析 Golang 的高级特性与工程级最佳实践,涵盖并发模型、内存管理、接口设计与错误处理策略。通过真实场景与代码对比,引导从“可运行”走向“高质量”,帮助构建高性能、可扩展、易维护的优雅 Go 代码体系。

1

2026.02.27

Golang 测试与调试专题:确保代码可靠性
Golang 测试与调试专题:确保代码可靠性

本专题聚焦 Golang 的测试与调试体系,系统讲解单元测试、表驱动测试、基准测试与覆盖率分析方法,并深入剖析调试工具与常见问题定位思路。通过实践示例,引导建立可验证、可回归的工程习惯,从而持续提升代码可靠性与可维护性。

0

2026.02.27

漫蛙app官网链接入口
漫蛙app官网链接入口

漫蛙App官网提供多条稳定入口,包括 https://manwa.me、https

56

2026.02.27

deepseek在线提问
deepseek在线提问

本合集汇总了DeepSeek在线提问技巧与免登录使用入口,助你快速上手AI对话、写作、分析等功能。阅读专题下面的文章了解更多详细内容。

4

2026.02.27

AO3官网直接进入
AO3官网直接进入

AO3官网最新入口合集,汇总2026年可用官方及镜像链接,助你快速稳定访问Archive of Our Own平台。阅读专题下面的文章了解更多详细内容。

53

2026.02.27

php框架基础教程
php框架基础教程

本合集涵盖2026年最新PHP框架入门知识与基础教程,适合初学者快速掌握主流框架核心概念与使用方法。阅读专题下面的文章了解更多详细内容。

1

2026.02.27

php框架怎么用
php框架怎么用

本合集专为零基础学习者打造,系统介绍主流PHP框架的安装、配置与基础用法,助你快速入门Web开发。阅读专题下面的文章了解更多详细内容。

4

2026.02.27

无禁词AI聊天软件下载大全
无禁词AI聊天软件下载大全

本合集精选多款免费、无违禁词限制的AI聊天软件,支持自定义角色、剧情畅聊,体验真实互动感。阅读专题下面的文章了解更多详细内容。

19

2026.02.27

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
nginx浅谈
nginx浅谈

共15课时 | 0.9万人学习

前端开发(基础+实战项目合集)
前端开发(基础+实战项目合集)

共60课时 | 4.2万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号