当前位置: 首页 > news >正文

延迟加载(Lazyload)三种实现方式

定义:延迟加载也称为惰性加载,即在长网页中延迟加载图像。用户滚动到它们之前,视口外的图像不会加载。这与图像预加载相反,在长网页上使用延迟加载将使网页加载更快。在某些情况下,它还可以帮助减少服务器负载。

举个例子来说明,当打开淘宝首页的时候,只有在浏览器窗口里的图片才会被加载,当你滚动首页向下滑的时候,进入视口内的图片才会被加载,而其它从未进入视口的图像不会也不会加载。

那么延迟加载有什么好处:
1. 首先它能提升用户的体验,试想一下,如果打开页面的时候就将页面上所有的图片全部获取加载,如果图片数量较大,对于用户来说简直就是灾难,会出现卡顿现象,影响用户体验。
2. 有选择性地请求图片,这样能明显减少了服务器的压力和流量,也能够减小浏览器的负担。

那么下面就介绍延迟加载的三种实现方式:

第一种:
首先将页面上的图片的 src 属性设为 loading.gif,而图片的真实路径则设置在 data-src 属性中,页面滚动的时候计算图片的位置与滚动的位置,当图片出现在浏览器视口内时,将图片的 src 属性设置为 data-src 的值,这样,就可以实现延迟加载。

下面是具体的实现代码:

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Lazyload 1</title><style>img {display: block;margin-bottom: 50px;height: 200px;}</style>
</head>
<body><img src="images/loading.gif" data-src="images/1.png"><img src="images/loading.gif" data-src="images/2.png"><img src="images/loading.gif" data-src="images/3.png"><img src="images/loading.gif" data-src="images/4.png"><img src="images/loading.gif" data-src="images/5.png"><img src="images/loading.gif" data-src="images/6.png"><img src="images/loading.gif" data-src="images/7.png"><img src="images/loading.gif" data-src="images/8.png"><img src="images/loading.gif" data-src="images/9.png"><img src="images/loading.gif" data-src="images/10.png"><img src="images/loading.gif" data-src="images/11.png"><img src="images/loading.gif" data-src="images/12.png"><script>function lazyload() {var images = document.getElementsByTagName('img');var len    = images.length;var n      = 0;      //存储图片加载到的位置,避免每次都从第一张图片开始遍历       return function() {var seeHeight = document.documentElement.clientHeight;var scrollTop = document.documentElement.scrollTop || document.body.scrollTop;for(var i = n; i < len; i++) {if(images[i].offsetTop < seeHeight + scrollTop) {if(images[i].getAttribute('src') === 'images/loading.gif') {images[i].src = images[i].getAttribute('data-src');}n = n + 1;}}}}var loadImages = lazyload();loadImages();          //初始化首页的页面图片window.addEventListener('scroll', loadImages, 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>
<html lang="en">
<head><meta charset="UTF-8"><title>Lazyload 2</title><style>img {display: block;margin-bottom: 50px;height: 200px;}</style>
</head>
<body><img src="images/loading.gif" data-src="images/1.png"><img src="images/loading.gif" data-src="images/2.png"><img src="images/loading.gif" data-src="images/3.png"><img src="images/loading.gif" data-src="images/4.png"><img src="images/loading.gif" data-src="images/5.png"><img src="images/loading.gif" data-src="images/6.png"><img src="images/loading.gif" data-src="images/7.png"><img src="images/loading.gif" data-src="images/8.png"><img src="images/loading.gif" data-src="images/9.png"><img src="images/loading.gif" data-src="images/10.png"><img src="images/loading.gif" data-src="images/11.png"><img src="images/loading.gif" data-src="images/12.png"><script>function throttle(fn, delay, atleast) {var timeout = null,startTime = new Date();return function() {var curTime = new Date();clearTimeout(timeout);if(curTime - startTime >= atleast) {fn();startTime = curTime;}else {timeout = setTimeout(fn, delay);}}}function lazyload() {var images = document.getElementsByTagName('img');var len    = images.length;var n      = 0;      //存储图片加载到的位置,避免每次都从第一张图片开始遍历       return function() {var seeHeight = document.documentElement.clientHeight;var scrollTop = document.documentElement.scrollTop || document.body.scrollTop;for(var i = n; i < len; i++) {if(images[i].offsetTop < seeHeight + scrollTop) {if(images[i].getAttribute('src') === 'images/loading.gif') {images[i].src = images[i].getAttribute('data-src');}n = n + 1;}}}}var loadImages = lazyload();loadImages();          //初始化首页的页面图片window.addEventListener('scroll', throttle(loadImages, 500, 1000), false);</script>
</body>
</html>

设置了 500ms 的延迟,和 1000ms 的间隔,当超过 1000ms 未触发该函数,则立即执行该函数,不然则延迟 500ms 执行该函数。

实现效果:可以看出有一定的延迟。
这里写图片描述
参考链接:实现图片懒加载(lazyload)

第三种: 使用 IntersectionObserver API

目前有一个新的 IntersectionObserver API,可以自动”观察”元素是否可见,Chrome 51+ 已经支持。

这里不过多介绍 IntersectionObserver API 的详细使用,感兴趣可以另外阅读下面的文章:

IntersectionObserver API 使用教程
Intersection Observer API

实现代码:简洁,但是浏览器尚未全部实现。

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Lazyload 3</title><style>img {display: block;margin-bottom: 50px;width: 800px;}</style>
</head>
<body><img src="images/loading.gif" data-src="images/1.png"><img src="images/loading.gif" data-src="images/2.png"><img src="images/loading.gif" data-src="images/3.png"><img src="images/loading.gif" data-src="images/4.png"><img src="images/loading.gif" data-src="images/5.png"><img src="images/loading.gif" data-src="images/6.png"><img src="images/loading.gif" data-src="images/7.png"><img src="images/loading.gif" data-src="images/8.png"><img src="images/loading.gif" data-src="images/9.png"><img src="images/loading.gif" data-src="images/10.png"><img src="images/loading.gif" data-src="images/11.png"><img src="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 = item.target;if(target.getAttribute('src') == 'images/loading.gif') {target.src = target.getAttribute('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

http://www.xdnf.cn/news/833563.html

相关文章:

  • 2024年最全速看!成为黑k必看13个网站,简称网站大全!_红黑联盟官方网站,2024年最新看看这篇文章吧
  • log4cpp初入门
  • linux查看7799端口使用情况,OEM12C安装文档
  • 使用Flash_TooL软件刷机Android 手机步骤
  • ADODB 使用说明
  • Manifest文件详解
  • IF函数超实用的12种经典用法
  • 函数PostEvent、triggerevent详解
  • 八款好用的浏览器兼容性测试工具推荐
  • 【深度学习】【机器学习】用神经网络进行入侵检测,NSL-KDD数据集,基于机器学习(深度学习)判断网络入侵,网络攻击,流量异常
  • 想染指系统架构?看这篇就够了
  • DevC++graphics.h库(1)库的下载与安装
  • 【windows】--- SQL Server 2008 超详细安装教程
  • 在 SpringBoot 中使用 ThreadPoolTaskScheduler 实现定时任务
  • 一位十年软件工程师告诉你什么是编程思想
  • 【最新】网站下载工具,整站下载工具汇总
  • 原生js中nextSibling和nextElementSibling的坑
  • 如何执行VMware P2V迁移|VMware Converter和替代方案
  • CppCon 2014 学习:Rolling Your Own Circuit Simulator
  • 工作中使用到的单词(软件开发)_第二版
  • 弱口令(Weak Password)总结和爆破工具
  • arm9芯片包括哪些?arm9如何应用
  • pascal编程语言介绍
  • 软件项目开发全套文档(规格说明书;详细设计;测试计划;验收报告)
  • 【飞桨AI实战】基于PP-OCR和ErnieBot的智能视频问答
  • DCT变换、DCT反变换、分块DCT变换
  • Labview2023安装教程(非常详细)从零基础入门到精通,看完这一篇就够了_labview安装教程(5)
  • 搭建大型分布式服务(二十七)如何通过Coding流水线CI/CD将SpringBoot服务部署到TKE容器集群
  • 如何获取搜索引擎的来源,以及搜索引擎的相关信息
  • 几个开源的运维管理系统介绍