前端必会的图片懒加载(三种方式)

 更新时间:2021年8月25日 12:00  点击:2185

一.何为懒加载🌃:

  在我们访问一个图片展示比较多的网页时,加载速度慢很多时候正是因为图片多导致,大量的img图片导致页面渲染的堵塞。当费了许多力气把全部图片和页面加载出来时而用户早已离去。另一方面,若用户只查看了网页的前面部分便离开,许多已经加载却因为处于网页底部而未呈现在视口区的图片,它们极大加重服务器压力了但是用户看都没看,白白浪费了性能。

  为了解决上面的问题需要引入图片懒加载,懒加载其实很好理解,重点就是一个‘懒'字。当用户滚动相应可视区域,若可视区域有图片便加载,而在可视区域外未加载过的图片它们先不加载,如果用户滚动可视区域到它们时它们再加载,否则一律不加载。这样一来就大大提高了网页渲染的性能和减少不必要的浪费。

二.实现懒加载🌄:

  首先,先定义一个基本的HTML页面模拟一些存在大量图片的网页,比如我用8个img 标签来模拟,同时定义一些基本css样式,代码与初始效果如下:

html:

    <img src="img/1.jpg" alt="xxx" />
    <img src="img/2.jpg" alt="xxx" />
    <img src="img/3.jpg" alt="xxx" />
    <img src="img/4.jpg" alt="xxx" />
    <img src="img/5.jpg" alt="xxx" />
    <img src="img/6.jpg" alt="xxx" />
    <img src="img/7.jpg" alt="xxx" />
    <img src="img/8.jpg" alt="xxx" />

css:

 * {
        margin: 0;
        padding: 0;
        box-sizing: border-box;
      }
      img {
        width: 500px;
        height: 300px;
        object-fit: cover;
        margin: 20px;
      }
      body {
        display: flex;
        flex-wrap: wrap;
        justify-content: space-evenly;
      }

初始效果如下,可以看到右边的控制台,8张图片在我一运行这个页面的时候就都一同被加载渲染了:

在这里插入图片描述  

下面是利用JavaScript实现懒加载的3种方式,原理都是判断图片是否出现在可视区后给图片赋值src属性。

2.1 第一种方式:

  首先,修改每一个img标签,利用HTML提供的 data- 属性来嵌入自定义数据,这个自定义数据我们存放这个标签原本的图片地址。同时,全部的图片的src属性我们都用一张同样的图表示,这个图一般可为显示载入中字样的图片。注意,如果多个img标签src引用的是同一张图片,那么只会加载一次,不会多次加载,所以我下面给每个图src定义同一张图。

    <img data-src="img/1.jpg" src="img/0.png" alt="xxx" />
    <img data-src="img/2.jpg" src="img/0.png" alt="xxx" />
    <img data-src="img/3.jpg" src="img/0.png" alt="xxx" />
    <img data-src="img/4.jpg" src="img/0.png" alt="xxx" />
    <img data-src="img/5.jpg" src="img/0.png" alt="xxx" />
    <img data-src="img/6.jpg" src="img/0.png" alt="xxx" />
    <img data-src="img/7.jpg" src="img/0.png" alt="xxx" />
    <img data-src="img/8.jpg" src="img/0.png" alt="xxx" />

此时页面效果如下,:

在这里插入图片描述

接下来用JavaScript实现当我们滚动滚动条时,如果图片出现在可视区,那么加载图片。加载图片其实就是给img标签src属性赋值为本来的地址,那么此时图片便会请求加载渲染出来。

 //获取全部img标签
var images = document.getElementsByTagName("img");

 window.addEventListener("scroll", (e) => {
    //当发生滚动事件时调用ergodic事件
    ergodic();
  });
  function ergodic() {
    // 遍历每一张图
    for (let i of images) {
      //判断当前图片是否在可视区内
      if (i.offsetTop <= window.innerHeight + window.scrollY) {
          //获取自定义data-src属性的值
          let trueSrc = i.getAttribute("data-src");
          //把值赋值给图片的src属性
          i.setAttribute("src", trueSrc);
      }
    }
  }
  //没发生滚动事件时也要先执行一次
  ergodic();

 其中, offsetTop 为元素距离顶部的距离;window.innerHeight 为当前窗口的高度;window.scrollY 为滚动距离;不难知道,当 i.offsetTop <= window.innerHeight + window.scrollY时图片就处于窗口可视区了。

此时效果如下,观察右侧控制台,发现当滚动时图片才加载:

在这里插入图片描述

2.2 第二种方式:

第二种方式其实和第一种差不多,只是计算图片是否在可视区方式不同,重复的部分就省略了,如下:

  window.addEventListener("scroll", (e) => {
        ergodic();
      });
      function ergodic() {
        for (let i of images) {
          //计算方式和第一种方式不同
          if (i.getBoundingClientRect().top < window.innerHeight) {
            let trueSrc = i.getAttribute("data-src");
            i.setAttribute("src", trueSrc);
          }
        }
      }
      ergodic();

 其中,getBoundingClientRect().top 为元素相对于窗口的位置;window.innerHeight 为当前窗口的高度;当元素对于窗口的位置小于当前窗口的高度时,那自然处于了窗口可视区了。

效果一样的:

在这里插入图片描述

2.3 第三种方式(优):

 其实上面两种方式已经大致实现懒加载,但是,它们都有一个缺点,就是一当发生滚动事件时,就发生了大量的循环和判断操作判断图片是否可视区里。这自然是不太好的,那是否有解决方法。这里就引入了一个叫 Intersection Observer 观察器接口,它是是浏览器原生提供的构造函数,使用它能省到大量的循环和判断。当然它的兼容可能不太好,看情况使用。

 Intersection Observer 是什么呢?这个构造函数的作用是它能够观察可视窗口与目标元素产生的交叉区域。简单来说就是当用它观察我们的图片时,当图片出现或者消失在可视窗口,它都能知道并且会执行一个特殊的回调函数,我们就利用这个回调函数实现我们的操作。概念枯燥难懂,直接看下面例子:

1.既然IntersectionObserver是浏览器原生提供的构造函数,先new一个实例:

 const observer = new IntersectionObserver(callback);

 其中它会有一个参数callback,参数为一个回调函数,当目标元素能看见会触发一次,目标元素看不见会再触发一次。

2.使用实例通过observer属性可以为每一张图片绑定一个观察器:

for (let i of images) {
        observer.observe(i);
      }

3.由上可以知道每张图片能看见会和看不见时都会触发一次callback回调函数,同时callback这个回调函数也有一个参数entries,我们可以运行触发这个回调函数看看它是什么:

 function callback(entries) {
      console.log(entries)
      }

在这里插入图片描述

 可以看到每次图片能看见会和看不见时都会触发一次callback回调函数,并输出了参数entries的内容。其实,entries为一个数组,而它的数组元素为当前改变了状态触发了事件的目标元素。其中有一个isIntersecting属性,当目标元素在视口看得见为它true,不在时它为 false 。我们就可以利用这个属性,当它为 true 时设置触发这个事件的图片的src属性值为data-src,开始加载。

function callback(entries) {
        for (let i of entries) {
          if (i.isIntersecting) {
              let img = i.target;
              let trueSrc = img.getAttribute("data-src");
              img.setAttribute("src", trueSrc);
          }
        } 
      }

 其中 target 事件属性返回触发事件的元素。当前,当回来滚动时,图片会一会可见一会不可见,它都是触发回调函数,所以当某图片已经加载时我们要停掉它的观察器。利用unobserve属性可停掉。

  function callback(entries) {
    for (let i of entries) {
      if (i.isIntersecting) {
          let img = i.target;
          let trueSrc = img.getAttribute("data-src");
          img.setAttribute("src", trueSrc);
          // 结束观察
          observer.unobserve(img);
      }
    } 
  }

完整代码:

 var images = document.getElementsByTagName("img");
   function callback(entries) {
    for (let i of entries) {
      if (i.isIntersecting) {
          let img = i.target;
          let trueSrc = img.getAttribute("data-src");
          img.setAttribute("src", trueSrc);
          observer.unobserve(img);
      }
    } 
  }
      const observer = new IntersectionObserver(callback);
      for (let i of images) {
        observer.observe(i);
      }

效果如下,实现懒加载:

在这里插入图片描述

三.总结:

  以上就为实现图片懒加载的全部内容啦。✨总的来说就是某些存在大量的img的网页如果页面渲染阶段就把图片全部加载,那会导致页面渲染的堵塞。为了解决引入图片懒加载,用户滚动相应可视区域,若可视区域有图片那么该图片才加载。其中核心就是给图片定义自定义属性data-src存放图片真的访问地址,当图片出现在可视区时才将data-src的值赋值给src属性,此时图片便加载。其中不止不可通过一些常见属性判断图片位置,还引入了IntersectionObserver观察器接口更少消耗的实现懒加载。

到此这篇关于前端必会的图片懒加载(三种方式)的文章就介绍到这了,更多相关图片懒加载内容请搜索猪先飞以前的文章或继续浏览下面的相关文章希望大家以后多多支持猪先飞!

[!--infotagslink--]

相关文章

  • 使用PHP+JavaScript将HTML页面转换为图片的实例分享

    这篇文章主要介绍了使用PHP+JavaScript将HTML元素转换为图片的实例分享,文后结果的截图只能体现出替换的字体,也不能说将静态页面转为图片可以加快加载,只是这种做法比较interesting XD需要的朋友可以参考下...2016-04-19
  • C#从数据库读取图片并保存的两种方法

    这篇文章主要介绍了C#从数据库读取图片并保存的方法,帮助大家更好的理解和使用c#,感兴趣的朋友可以了解下...2021-01-16
  • Photoshop古装美女图片转为工笔画效果制作教程

    今天小编在这里就来给各位Photoshop的这一款软件的使用者们来说说把古装美女图片转为细腻的工笔画效果的制作教程,各位想知道方法的使用者们,那么下面就快来跟着小编一...2016-09-14
  • Python 图片转数组,二进制互转操作

    这篇文章主要介绍了Python 图片转数组,二进制互转操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2021-03-09
  • php抓取网站图片并保存的实现方法

    php如何实现抓取网页图片,相较于手动的粘贴复制,使用小程序要方便快捷多了,喜欢编程的人总会喜欢制作一些简单有用的小软件,最近就参考了网上一个php抓取图片代码,封装了一个php远程抓取图片的类,测试了一下,效果还不错分享...2015-10-30
  • jquery左右滚动焦点图banner图片鼠标经过显示上下页按钮

    jquery左右滚动焦点图banner图片鼠标经过显示上下页按钮...2013-10-13
  • 利用JS实现点击按钮后图片自动切换的简单方法

    下面小编就为大家带来一篇利用JS实现点击按钮后图片自动切换的简单方法。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧...2016-10-25
  • Photoshop枪战电影海报图片制作教程

    Photoshop的这一款软件小编相信很多的人都已经是使用过了吧,那么今天小编在这里就给大家带来了用Photoshop软件制作枪战电影海报的教程,想知道制作步骤的玩家们,那么下面...2016-09-14
  • js实现上传图片及时预览

    这篇文章主要为大家详细介绍了js实现上传图片及时预览的相关资料,具有一定的参考价值,感兴趣的朋友可以参考一下...2016-05-09
  • python opencv通过4坐标剪裁图片

    图片剪裁是常用的方法,那么如何通过4坐标剪裁图片,本文就详细的来介绍一下,感兴趣的小伙伴们可以参考一下...2021-06-04
  • 使用PHP下载CSS文件中的图片的代码

    共享一段使用PHP下载CSS文件中的图片的代码 复制代码 代码如下: <?php //note 设置PHP超时时间 set_time_limit(0); //note 取得样式文件内容 $styleFileContent = file_get_contents('images/style.css'); //not...2013-10-04
  • PHP swfupload图片上传的实例代码

    PHP代码如下:复制代码 代码如下:if (isset($_FILES["Filedata"]) || !is_uploaded_file($_FILES["Filedata"]["tmp_name"]) || $_FILES["Filedata"]["error"] != 0) { $upload_file = $_FILES['Filedata']; $fil...2013-10-04
  • 微信小程序如何获取图片宽度与高度

    这篇文章主要给大家介绍了关于微信小程序如何获取图片宽度与高度的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2021-03-10
  • Angular性能优化之第三方组件和懒加载技术

    这篇文章主要介绍了Angular性能优化之第三方组件和懒加载技术,对性能优化感兴趣的同学,可以参考下...2021-05-11
  • C#中图片旋转和翻转(RotateFlipType)用法分析

    这篇文章主要介绍了C#中图片旋转和翻转(RotateFlipType)用法,实例分析了C#图片旋转及翻转Image.RotateFlip方法属性的常用设置技巧,需要的朋友可以参考下...2020-06-25
  • ps怎么制作图片阴影效果

    ps软件是现在很多人比较喜欢的,有着非常不错的使用效果,这次文章就给大家介绍下ps怎么制作图片阴影效果,还不知道制作方法的赶紧来看看。 ps图片阴影效果怎么做方法/...2017-07-06
  • OpenCV如何去除图片中的阴影的实现

    这篇文章主要介绍了OpenCV如何去除图片中的阴影的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2021-03-29
  • C#将图片和字节流互相转换并显示到页面上

    本文主要介绍用C#实现图片转换成字节流,字节流转换成图片,并根据图片路径返回图片的字节流,有需要的朋友可以参考下...2020-06-25
  • JavaScript 如何禁止用户保存图片

    这篇文章主要介绍了JavaScript 如何禁止用户保存图片,帮助大家完成需求,更好的理解和使用JavaScript,感兴趣的朋友可以了解下...2020-11-19
  • php上传图片学习笔记与心得

    我们在php中上传文件就必须使用#_FILE变量了,这个自动全局变量 $_FILES 从 PHP 4.1.0 版本开始被支持。在这之前,从 4.0.0 版本开始,PHP 支持 $HTTP_POST_FILES 数组。这...2016-11-25