延迟加载(Lazyload)三种实现方式
定义:延迟加载也称为惰性加载,即在长网页中延迟加载图像。用户滚动到它们之前,视口外的图像不会加载。这与图像预加载相反,在长网页上使用延迟加载将使网页加载更快。在某些情况下,它还可以帮助减少服务器负载。
举个例子来说明,当打开淘宝首页的时候,只有在浏览器窗口里的图片才会被加载,当你滚动首页向下滑的时候,进入视口内的图片才会被加载,而其它从未进入视口的图像不会也不会加载。
那么延迟加载有什么好处:
1、首先它能提升用户的体验,试想一下,如果打开页面的时候就将页面上所有的图片全部获取加载,如果图片数量较大,对于用户来说简直就是灾难,会出现卡顿现象,影响用户体验。
2、有选择性地请求图片,这样能明显减少了服务器的压力和流量,也能够减小浏览器的负担。
那么下面就介绍延迟加载的三种实现方式:
第一种
首先将页面上的图片的 src 属性设为 loading.gif,而图片的真实路径则设置在 data-src 属性中,页面滚动的时候计算图片的位置与滚动的位置,当图片出现在浏览器视口内时,将图片的 src 属性设置为 data-src 的值,这样,就可以实现延迟加载。
下面是具体的实现代码:
<!DOCTYPE <html "en" > <head> <meta "UTF-8" > <title>Lazyload <style> img display: margin-bottom: height: } </style> </head> <body> <img "images/loading.gif" data-src= "images/1.png" > <img "images/loading.gif" data-src= "images/2.png" > <img "images/loading.gif" data-src= "images/3.png" > <img "images/loading.gif" data-src= "images/4.png" > <img "images/loading.gif" data-src= "images/5.png" > <img "images/loading.gif" data-src= "images/6.png" > <img "images/loading.gif" data-src= "images/7.png" > <img "images/loading.gif" data-src= "images/8.png" > <img "images/loading.gif" data-src= "images/9.png" > <img "images/loading.gif" data-src= "images/10.png" > <img "images/loading.gif" data-src= "images/11.png" > <img "images/loading.gif" data-src= "images/12.png" > <script> function lazyload() var images 'img' ); var len var n //存储图片加载到的位置,避免每次都从第一张图片开始遍历 return function () var seeHeight var scrollTop for ( var i if (images[i].offsetTop if (images[i].getAttribute( 'src' ) 'images/loading.gif' ) images[i].src 'data-src' ); } n } } } } var loadImages loadImages(); //初始化首页的页面图片 window.addEventListener( 'scroll' , false ); </script> </body> </html> |
比较 image 的 offsetTop 与 seeHeight + scrollTop 的大小,当小于时则说明图片已经出现过在视口中,这时候继续判断图片是否已经替换过,如果没有替换过,则进行替换。
实现的效果:不断滑动页面时,图片延迟加载
你可以拷贝我的代码去进行实验,但是请确保 HTML 同目录下有 images 目录并且含有 1~12.png 和 loading.gif。
需要提及的是变量 n 是用来保存已经加载的图片数量,避免每次都从第一张图片开始遍历,提升性能。上面的代码用到了 JS 闭包的知识,如果你不太熟悉的话,可以自行百度一下。
第二种
上面的代码是没什么问题,但是性能偏差。如果直接将函数绑定在 scroll 事件上,当页面滚动时,函数会被高频触发,这非常影响浏览器的性能。我粗略地估计一下,当简单地滚动一下页面,函数至少触发了十来次,这显然是十分没必要的。
所以在做事件绑定的时候,可以对 lazyload 函数进行函数节流(throttle)与函数去抖(debounce)处理。
这里我并不再另外介绍这两种方案,如果你想了解的话可以阅读:JS魔法堂:函数节流(throttle)与函数去抖(debounce) – ^_^肥仔John – 博客园
简单说来:
- Debounce:一部电梯停在某一个楼层,当有一个人进来后,20秒后自动关门,这20秒的等待期间,又一个人按了电梯进来,这20秒又重新计算,直到电梯关门那一刻才算是响应了事件。
- Throttle:好比一台自动的饮料机,按拿铁按钮,在出饮料的过程中,不管按多少这个按钮,都不会连续出饮料,中间按钮的响应会被忽略,必须要等这一杯的容量全部出完之后,再按拿铁按钮才会出下一杯。
下面就是经过 throttle 处理后的代码:
<!DOCTYPE <html "en" > <head> <meta "UTF-8" > <title>Lazyload <style> img display: margin-bottom: height: } </style> </head> <body> <img "images/loading.gif" data-src= "images/1.png" > <img "images/loading.gif" data-src= "images/2.png" > <img "images/loading.gif" data-src= "images/3.png" > <img "images/loading.gif" data-src= "images/4.png" > <img "images/loading.gif" data-src= "images/5.png" > <img "images/loading.gif" data-src= "images/6.png" > <img "images/loading.gif" data-src= "images/7.png" > <img "images/loading.gif" data-src= "images/8.png" > <img "images/loading.gif" data-src= "images/9.png" > <img "images/loading.gif" data-src= "images/10.png" > <img "images/loading.gif" data-src= "images/11.png" > <img "images/loading.gif" data-src= "images/12.png" > <script> function throttle(fn, var timeout null , startTime new Date(); return function () var curTime new Date(); clearTimeout(timeout); if (curTime fn(); startTime } else { timeout } } } function lazyload() var images 'img' ); var len var n //存储图片加载到的位置,避免每次都从第一张图片开始遍历 return function () var seeHeight var scrollTop for ( var i if (images[i].offsetTop if (images[i].getAttribute( 'src' ) 'images/loading.gif' ) images[i].src 'data-src' ); } n } } } } var loadImages loadImages(); //初始化首页的页面图片 window.addEventListener( 'scroll' , false ); </script> </body> </html> |
设置了 500ms 的延迟,和 1000ms 的间隔,当超过 1000ms 未触发该函数,则立即执行该函数,不然则延迟 500ms 执行该函数。
实现效果:可以看出有一定的延迟。
参考链接:实现图片懒加载(lazyload)
第三种: 使用 IntersectionObserver API
目前有一个新的 IntersectionObserver API,可以自动”观察”元素是否可见,Chrome 51+ 已经支持。
这里不过多介绍 IntersectionObserver API 的详细使用,感兴趣可以另外阅读下面的文章:
实现代码:简洁,但是浏览器尚未全部实现。
<!DOCTYPE <html "en" > <head> <meta "UTF-8" > <title>Lazyload <style> img display: margin-bottom: width: } </style> </head> <body> <img "images/loading.gif" data-src= "images/1.png" > <img "images/loading.gif" data-src= "images/2.png" > <img "images/loading.gif" data-src= "images/3.png" > <img "images/loading.gif" data-src= "images/4.png" > <img "images/loading.gif" data-src= "images/5.png" > <img "images/loading.gif" data-src= "images/6.png" > <img "images/loading.gif" data-src= "images/7.png" > <img "images/loading.gif" data-src= "images/8.png" > <img "images/loading.gif" data-src= "images/9.png" > <img "images/loading.gif" data-src= "images/10.png" > <img "images/loading.gif" data-src= "images/11.png" > <img "images/loading.gif" data-src= "images/12.png" > <script> function query(selector) return Array.from(document.querySelectorAll(selector)); } var io new IntersectionObserver( function (items) items.forEach( function (item) var target if (target.getAttribute( 'src' ) 'images/loading.gif' ) target.src 'data-src' ); } }) }); query( 'img' ).forEach( function (item) io.observe(item); }); </script> </body> </html> |
1、IntersectionObserver 传入一个回调函数,当其观察到元素集合出现时候,则会执行该函数。
2、io.observe 即要观察的元素,要一个个添加才可以。
3、io 管理的是一个数组,当元素出现或消失的时候,数组添加或删除该元素,并且执行该回调函数。
实现效果:
原文地址:https://zhuanlan.zhihu.com/p/25455672
延迟加载(Lazyload)三种实现方式的更多相关文章
- MyBatis 延迟加载的三种加载方式深入,你get了吗?
延迟加载 延迟加载对主对象都是直接加载,只有对关联对象是延迟加载. 延迟加载可以减轻数据库的压力, 延迟加载不可是一条SQL查询多表信息,这样构不成延迟加载,会形成直接加载. 延迟加载分为三种类型: ...
- 通过三个DEMO学会SignalR的三种实现方式
一.理解SignalR ASP .NET SignalR 是一个ASP .NET 下的类库,可以在ASP .NET 的Web项目中实现实时通信(即:客户端(Web页面)和服务器端可以互相实时的通知消息 ...
- Hive metastore三种配置方式
http://blog.csdn.net/reesun/article/details/8556078 Hive的meta数据支持以下三种存储方式,其中两种属于本地存储,一种为远端存储.远端存储比较适 ...
- django 模板语法和三种返回方式
模板 for循环 {% for athlete in athlete_list %} <li>{{ athlete.name }}</li> {% endfor %} if语句 ...
- js的三种继承方式及其优缺点
[转] 第一种,prototype的方式: //父类 function person(){ this.hair = 'black'; this.eye = 'black'; this.skin = ' ...
- spring ioc三种注入方式
spring ioc三种注入方式 IOC ,全称 (Inverse Of Control) ,中文意思为:控制反转 什么是控制反转? 控制反转是一种将组件依赖关系的创建和管理置于程序外部的技术. 由容 ...
- Map三种遍历方式
Map三种遍历方式 package decorator; import java.util.Collection; import java.util.HashMap; import java.util ...
- php 递归函数的三种实现方式
递归函数是我们常用到的一类函数,最基本的特点是函数自身调用自身,但必须在调用自身前有条件判断,否则无限无限调用下去.实现递归函数可以采取什么方式呢?本文列出了三种基本方式.理解其原来需要一定的基础知识 ...
- JSON的三种解析方式
一.什么是JSON? JSON是一种取代XML的数据结构,和xml相比,它更小巧但描述能力却不差,由于它的小巧所以网络传输数据将减少更多流量从而加快速度. JSON就是一串字符串 只不过元素会使用特定 ...
随机推荐
- zTree的核心处理逻辑
zTree 是一个前端树形结构的插件. 使用起来很简单,我们重点关注一下插件的核心代码. 首先,zTree需要如下的数据结构: let areaData = [ { "id": & ...
- kali linux (Raspberry Pi 3b) 更新失败 出现上面的问题
Invalid signature for Kali Linux repositories : “The following signatures were invalid: EXPKEYSIG ED ...
- SAP常见问题与解决办法(转)
1.A:在公司代码分配折旧表时报错? 在公司代码分配折旧表时报错,提示是“3000 的公司代码分录不完全-参见长文本” 希望各位大侠帮我看看.3000 的公司代码分录不完全-参见长文本 R: a.你把 ...
- Win10家庭版卸载Mysql 8.0.13实录
因为重度嫌弃Mysql 8.0.xxx的各种妖魔鬼怪,所以想卸载了.但是,百度了很多文章,日期也是近几个月,但是却并不适用.所以特写此文记录一下. 按照百度万金油通用第一步,就是要停止MySQL的服务 ...
- php如何将base64数据流文件转换为图片文件?
2017-03-07 在开发中,自己遇到一个前端在上传图片的时候,使用的base64数据流文件显示的图片. 也就是说 <img src="data:image/jpg;base64,& ...
- Python起源与发展
Python的创始人为吉多*范罗苏姆(Gudio van Rossum) 1.1989年的圣诞节期间,吉多*范罗苏姆为了在阿姆斯特丹打发时间,决心开发一个新的解释程序,作为ABC语言的一种继承. 2. ...
- python入门(续)
类和方法 创建类 class A(object): def add(self, a,b ): return a+b count = A() print(count.add(3,5)) 初始化工作 cl ...
- 第三章 最简单的C程序设计——顺序程序设计
一.数据的表现形式及其运算 1.常量和变量 在计算机高级语言中,数据有两种表现形式:常量和变量. 1.1.常量 在程序运行过程中,其值不能被改变的量称为常量.如:5,6,32,0.111. 数值常量就 ...
- python2.7练习小例子(十七)
17):题目:求s=a+aa+aaa+aaaa+aa...a的值,其中a是一个数字.例如2+22+222+2222+22222(此时共有5个数相加),几个数相加由键盘控制. 程序分析: ...
- 从C到C++ (1)
从C到C++ 一. bool类型 bool取值false和true,是0和1的区别: false可以代表0,但true有很多种,并非只有1. 二. const限定符 常量在定义后就不能修改,所以定义时 ...