彻底弄懂图片懒加载及底层实现原理

news2024/9/20 1:01:35
我们都知道图片懒加载是前端性能优化比较常见的一个手段,那么,你真的了解图片懒加载吗,本文将带你从简单到复杂一步一步彻底弄懂其底层实现原理。

试想一下,假设用户在访问我们的某个页面时,一开始就加载页面的全部图片,如果我们的网站中有大量的图片,那么整个加载过程是非常耗时的,如果这个时候用户的网络正好又是非常差的情况下,那么我们的网站就会卡在某个地方,一直加载。整个过程用户的体验效果是非常差的,这时候就需要利用图片懒加载技术。

简单实现图片懒加载
思路:给图片一个src属性存储一个加载动画的图片,data-src存储真实的图片,在图片每一进入可视区域的时候先加载加载动画的图片,等真正进入可视区域再加载真实图片。
1.获取屏幕可视区域的高度
document.documentElement.clientHeight
在这里插入图片描述
2.获取元素相对于文档顶部的高度
element.offsetTop
在这里插入图片描述
3.获取滚动条的高度
document.documentElement.scrollTop
在这里插入图片描述
当元素相对于文档顶部的高度<屏幕可视区域的高度+滚动条的高度
说明图片已经在视野范围内了,可以加载图片,下面是具体的代码实现

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>

<body>
  <img src="./img/loading.gif" data-src="./img/1.png" alt="">
  <img src="./img/loading.gif" data-src="./img/2.png" alt="">
  <img src="./img/loading.gif" data-src="./img/3.png" alt="">
  <img src="./img/loading.gif" data-src="./img/4.png" alt="">
  <img src="./img/loading.gif" data-src="./img/5.png" alt="">
  <img src="./img/loading.gif" data-src="./img/6.png" alt="">
</body>

<script>
    let num = document.getElementsByTagName("img").length
    let imgs = document.getElementsByTagName("img")

    let n = 0
    function lazyload(imgs){
      //获取可视区域的高度
      let visibleHeight = document.documentElement.clientHeight
      let scrollTop = document.documentElement.scrollTop || document.body.scrollTop

      for (let i = n; i < num; i++){
        if (imgs[i].offsetTop < visibleHeight + scrollTop) {
          if (imgs[i].getAttribute("src") === "./img/loading.gif") {
            imgs[i].src = img[i].getAttribute("data-src")
          }
          n = i + 1 // 加载过的图片防止二次加载
        }
      }
    }
    window.onload = window.onscroll = function () { 
      //onscroll()在滚动条滚动的时候触发
      lazyLoad(imgs);
    }
</script>
</html>

使用getBoundingClientRect()实现图片懒加载
getBoundingClientRect()用于获得页面中某个元素的左,上,右和下分别相对浏览器视窗的位置。 是DOM元素到浏览器可视范围的距离。

思路:只需要获取img元素相对于视口的顶点位置rectObject.top,只要这个值小于浏览器的高度window.innerHeight就说明进入可视区域。
实现方法

function isInVisible(el){
  const bound = el.getBoundingClientRect();
  const clientHeight = window.innerHeight;
  return bound.top <= clientHeight;
}
只需把上面代码的
//imgs[i].offsetTop < visibleHeight + scrollTop替换成isInVisible(imgs[i])就可以了

使用IntersectionObserver实现图片懒加载
IntersectionObserver可以观察一个元素是否在视窗可见。
使用方法

let io = new IntersectionObserver(callback, option);
/ 开始观察
io.observe(document.getElementById('container'));

// 停止观察
io.unobserve(element);

// 关闭观察器
io.disconnect();

具体实现代码

    const imgs =  document.querySelectorAll('img')
    function lazyLoad(target) {
      const io = new IntersectionObserver((entries, observer) => {
        entries.forEach(entrie => {
          if (entrie.isIntersecting) {
            const img = entrie.target;
            const src = img.getAttribute('data-src');
            img.setAttribute('src', src)
            observer.unobserve(img); // 停止监听已开始加载的图片
          }

        })
      }, {});
      io.observe(target)
    }

    imgs.forEach(img => {
      lazyLoad(img);
    })

好了,今天的分享就到这里!

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

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

相关文章

Vue中组件通信-$attrs与$listeners

组件通信-$attrs与$listeners1.$attrs父子组件通信的一种$attrs与$listeners ---- 父子组件通信$attrs&#xff1a;组件实例的属性&#xff0c;可以获取到父亲传递的props数据&#xff08;前提子组件没有通过props接受&#xff09;$listeners&#xff1a;组件实例的属性&#x…

【AAAI2023】Ultra-High-Definition Low-Light Image Enhancement

【AAAI2023】Ultra-High-Definition Low-Light Image Enhancement: A Benchmark and Transformer-Based Method 代码&#xff1a;https://github.com/TaoWangzj/LLFormer 这个论文首先构建了ultra-high definition low-light &#xff08;UHD-LOL&#xff09;数据集&#xff0c…

Revit建模操作:地面拼花效果做法和构件上色

一、Revit中如何快速做出地面拼花效果 一般大厅地面都会采用拼花做装饰&#xff0c;下面给大家推荐一种快速做出拼花效果的方法。 1.在Revit中导入地面铺装的CAD图纸&#xff0c;通过拾取底图的线&#xff0c;配合绘制命令分别建立各个形状的楼板&#xff0c;如图1所示&#xf…

虚拟DOM与render函数

目录 一、虚拟DOM 1、虚拟DOM是什么 2、为什么要使用虚拟DOM &#xff08;1&#xff09;浏览器显示网页的五步过程&#xff1a; &#xff08;2&#xff09;虚拟DOM的优点 3、Diff算法 二、VNode简介 1、VNode是什么 2、VNode的作用 3、VNode的优点 4、VNode如何生成&a…

【FreeRTOS】详细讲解FreeRTOS中消息队列并通过示例讲述其用法

讲解FreeRTOS中消息队列及其用法使用消息队列的原因消息队列函数解析示例遇到的问题使用消息队列的原因 在裸机系统中&#xff0c;两个程序间需要共享某个资源通常使用全局变量来实现&#xff1b;但在含操作系统(下文就拿FreeRTOS举例)的开发中&#xff0c;则使用消息队列完成。…

MonekyRunner

MonekyRunner 文章目录MonekyRunner一、简介二、JDK环境变量三、配置Android SDK环境变量3.1.下载并解压&#xff1a;3.2.环境变量&#xff1a;3.3.查看MonkeyRunner&#xff1a;四、编写Python脚本五、运行脚本一、简介 MonkeyRunner是Android SDK中自带的工具之一&#xff0…

python3:基础语法、及6种基本数据类型、找到字典的下标 index、获取list中指定元素的位置索引

基础语法 源码文件以 UTF-8 编码&#xff0c;所有字符串都是 unicode 字符串 Python 3 中&#xff0c;可以用中文作为变量名&#xff0c;非 ASCII 标识符也是允许的 标识符 第一个字符必须是字母表中字母或下划线 _ 。 标识符的其他的部分由字母、数字和下划线组成。 标识…

Java---微服务---微服务保护Sentinel

微服务保护Sentinel1.初识Sentinel1.1.雪崩问题及解决方案1.1.1.雪崩问题1.1.2.超时处理1.1.3.仓壁模式1.1.4.断路器1.1.5.限流1.1.6.总结1.2.服务保护技术对比1.3.Sentinel介绍和安装1.3.1.初识Sentinel1.3.2.安装Sentinel1.4.微服务整合Sentinel2.流量控制2.1.簇点链路2.1.快…

【自然语言处理】基于sklearn-crfsuite进行命名实体识别

基于sklearn-crfsuite进行命名实体识别0. 条件随机场1. 训练数据2. 特征提取3. 训练一个CRF模型4. 评估5. 超参数优化6. 检查参数空间7. 检查在测试数据上的最优估计器8.检查分类器学到了什么东西9.检查模型权重10. 定制化11.在控制台中进行格式化参考资料本文中&#xff0c;针…

一种前端无源码定制化开发能力专利解读

背景 目前市面上一些web前端工程在打包发布之前都会进行代码混淆加密。代码混淆(Obfuscated code)是将计算机程序的代码&#xff0c;转换成一种功能上等价&#xff0c;但是难于阅读和理解的形式的行为。代码混淆可以用于程序源代码&#xff0c;也可以用于程序编译而成的中间代…

Leetcode刷题Day38-------------------动态规划

Leetcode刷题Day38-------------------动态规划 1. 理论基础 文章链接&#xff1a;https://programmercarl.com/%E5%8A%A8%E6%80%81%E8%A7%84%E5%88%92%E7%90%86%E8%AE%BA%E5%9F%BA%E7%A1%80.html视频链接&#xff1a;https://www.bilibili.com/video/BV13Q4y197Wg题目链接&a…

GBASE荣获“2022证券基金行业信息技术应用创新联盟年度优秀成员奖

日前&#xff0c;证券基金行业信息技术应用创新联盟2022年度峰会于上海成功举办&#xff0c;在会上&#xff0c;GBASE南大通用作为联盟成员单位&#xff0c;积极相应联盟号召&#xff0c;有力支撑证券信创建设&#xff0c;荣获“2022证券基金行业信息技术应用创新联盟年度优秀成…

第一章 Arm 架构概述(2023新)

第一章 启发式 Arm 架构解读 第二章 CPU微架构 第三章 系统微架构 第四章 总线微架构 第五章 监控微架构 第六章 安全微架构 第七章 虚拟化微架构 第八章 Armv9-A 架构 第九章 Armv8-M 架构 第十章 Armv8-R 架构 第十一章 Cortex-A715 解读 第十二章 Cortex-X3 解读…

图片怎么转成PDF格式?介绍三种转换思路

PDF文件作为一类办公常见格式&#xff0c;很多场合都会使用到。有时我们需要将图片转成PDF格式以方便归纳整理。图片资料怎么转成PDF呢&#xff1f;给大家介绍几个手机和电脑都可以用的方式。希望对你有帮助。方法一、用文件自带的转换功能将图片转成PDF随意打开一个PDF文件后&…

Github每日精选(第94期):免费网页在线情况监控

Upptime Upptime 是开源的正常运行时间监控和状态页面&#xff0c;完全由 GitHub Actions、Issues 和 Pages 提供支持。 Upptime 是 [GitHub Actions] 的一个非常巧妙的用法。您基本上可以根据需要获得免费的可配置正常运行时间监视器。 github 地址在这里。 特点 利用 G…

CTPN的Python实现笔记一

文章目录一、疑难代码讲解1. 文本框左上角标注置信度(1) s str(round(i[-1] * 100, 2)) %(2) cv2.putText() 函数(3) cv2.line()函数2. 文本框进行扩展操作3. 文本框进行NMS操作(1) 非极大值抑制函数def nms(dets, thresh):a. order scores.argsort()[::-1]b. xx1 np.maxim…

[oeasy]python0068_控制序列_清屏_控制输出位置_2J

光标位置 回忆上次内容 上次了解了键盘演化的过程 ESC 从 组合键到 独立按键 ESC 的目的 是进入控制序列配置控制信息 控制信息 \033[y;xH 设置光标位置\033[2J 清屏 这到底怎么控制来着&#xff1f;&#xff1f;&#xff1f;&#x1f914;现在 系统里 这些行为 是谁来实现的…

【机器学习 - 6】:梯度下降法(第一篇)

文章目录梯度下降法的理解图解极值点和最值点梯度下降法的求导运算公式推导梯度下降法的实现梯度下降法的理解 梯度下降法不是一个机器学习算法&#xff0c;既不是在做监督学习&#xff0c;也不是在做非监督学习&#xff0c;是一种基于搜索的最优化方法。 作用&#xff1a;最小…

【2319. 判断矩阵是否是一个 X 矩阵】

来源&#xff1a;力扣&#xff08;LeetCode&#xff09; 描述&#xff1a; 如果一个正方形矩阵满足下述 全部 条件&#xff0c;则称之为一个 X 矩阵 &#xff1a; 矩阵对角线上的所有元素都 不是 0 矩阵中所有其他元素都是 0 给你一个大小为 n x n 的二维整数数组 grid &a…

JVM虚拟机知识总结

什么是虚拟机&#xff1f;从字面意思上来看&#xff0c;顾名思义即使一台虚拟的计算机&#xff0c;用来执行虚拟的计算机指令&#xff0c;从大体上来看&#xff0c;虚拟机一般分为两种。一种是系统虚拟机&#xff0c;另外一种是程序虚拟机。系统虚拟机&#xff1a;代表为VMware…