前端实现图片的懒加载

简介: 前端实现图片的懒加载

前言 🛰🛰


我们在浏览网页的时候,比如像淘宝京东等一些大型的电商网站时,会发现会有很多的图片,如果一开始就展示所有的图片,势必会影响道性能,也对用户的体验不是很好,那么这个时候我通常就会使用图片的懒加载技术


什么是懒加载呢?🐤🐤


对于懒加载顾名思义就是当页面一开始渲染时不执行所有所有图片的渲染工作,而是当用户滚动页面时滚动到了这个图片,需要该图片加载时在加载图片,使用懒加载可以减少初次打开网站的时候的加载速度,提高网站的响应速度。


实现原理 🔑🔑


对于普通的网页渲染的时候,如果直接在src中引用url来展示图片,那么网页在渲染的时候就会下载该图片,而懒加载则是将图片存储在data-src中,一开始的时候并不直接渲染,当页面滚动到课时区域的时候,先通过getAttribute获取data-src中的url,然后通过setAttribute方法给img元素设置src,这样就完成了懒加载的核心思路。


实现方式 ⛹️‍♀️⛹️‍♀️


通过滚动监听+getBoundingClientRect实现


废话不多说,我们先实现一下核心的代码(JavaScript部分)

// 封装立即执行函数
((doc, win) => {
  //    获取图片数组
  const imgs = doc.querySelectorAll("img");
  function Toscroll() {
    imgs.forEach((item) => {
      //    获取图片到可视区域顶部的距离
      const imgRect = item.getBoundingClientRect();
      //   如果两者的差值是小于零的那么表示该图片在可视区域之内
      if (imgRect.top < window.innerHeight && imgRect.bottom > 0) {
        //  获取data-src中的url注意这里的写法,这是特有的
        let imgSrc = item.dataset.src;
        item.setAttribute("src", imgSrc);
      }
    });
  }
  Toscroll();
  window.addEventListener("scroll", Toscroll);
})(document, window);

这里因为代码很多都是重复的,只有图片不太一样,所以HTML部分不全部展示。

<div>
<p>Lorem ipsum dolor, sit amet consectetur adipisicing elit. Molestiae praesentium asperiores recusandae,
 exercitationem autem a inventore! Vel eaque ullam provident, quas excepturi molestias beatae, rerum placeat
autem sequi inventore laudantium.
    ...
</p>
 <div class="img">
<img data-src="./image/图片1.jpg" src="./image/未加载在出来.jpg">
     ....
</div>       
</div>

讲解一下实现的核心思路:

首先大家肯定比较好奇getBoundingClientRect是什么,其实他返回是一个对象,表示了当前盒子在浏览器中的位置以及自身占据的空间的大小,除了width和height之外,其他的属性其实可以理解为相对于视窗左上角来计算出来的,下面我用一张图来给大家演示一下。

image.png

那么有了这个属性有什么作用呢?我们可以根据获取到的top值来和window.innerHeight进行对比,如果top<innerHeight,并且bottom的值>0,则说明此时图片在可视区域内,那么此时就可以考虑显示真正的图片。

这里有一个小的技巧,我们在img元素上面设置的data-src,可以通过在遍历时通过item.dataset.src来拿到。然后通过setAttribute来设置src,当然可以通过getAttribute来获取。

但是我们还是要对细节进行一下优化,因为每当我们滑动滚轮的时候就会触发事件,这样事件触发的就太频繁了,所以我们就可以进行一下节流操作.这样我们就实现了图片的懒加载

((doc, win) => { 
    .....
//  节流函数
  function throttle(fn, time) {
    var begin = new Date().getTime();
    return function () {
      var _this = this;
      var cur = new Date().getTime();
      var args = arguments;
      if (cur - begin >= time) {
        fn.apply(_this, args);
        begin = cur;
      }
    };
  }
 window.addEventListener("scroll", throttle(Toscroll, 1000), false);
})(document, window);    


通过intersectionObserve来实现 🌶🌶


废话不多说,直接先上代码

((doc) => {
  let imgs = doc.querySelectorAll("img");
  //   console.log(imgs);
  function lazyLoading() {
    let observer = new IntersectionObserver((entires) => {
      console.log(entires);
      entires.forEach((item) => {
        // 获取到原来图片的元素
        let oImg = item.target;
        if (item.intersectionRatio > 0 && item.intersectionRatio <= 1) {
          oImg.setAttribute("src", oImg.dataset.src);
          observer.unobserve(item.target);
        }
      });
    });
    imgs.forEach((item) => {
      observer.observe(item);
    });
  }
  lazyLoading();
})(document);

首先介绍一下这个API:

  • intersectionObserve是浏览器原生提供的构造函数,接受两个参数:callback是可见性变化时的回调函数,option是配置对象(该参数可选),这个这个构造函数返回的是一个观察器实例,这个实例中需要调用observe方法传入一个DOM对象,可以用来指定观测那个DOM节点,当我们需要监测多个DOM节点的时候就需要多次调用observe方法。
  • 然后我们需要注意的是IntersectionObserver构造函数中的回调函数,当目标元素的可见性发生变化时(比如图片进入可见区或者离开可见区域)就会调用这个回调函数,同样这个回调函数接收一个参数,他是一个数组,其中的每一个元素都是IntersectionObserverEntry对象。
  • 这个对象中包含多个属性,比如代表原来监视的元素的target,我们可以通过这个获取DOM节点,还有就是代表所监视元素有多少进入了可视区域的intersectionRatio,可以用它来判断是否进入了可视区域。具体就是判断他的值是否在0到1之间。


预览效果


image.png

由此可以看出 不管是以上的那中方式都可以实现懒加载,大家可以根据个人的喜好来实现,当然使用API肯定是要相对的简单一些,

从右侧的网络请求状态我们可以看出,使用了图片懒加载之后,只有图片进入可视区域之后才会被加载。这样在一些图片特别多的网站中,这样就可以提升性能,避免在一开始就进行大量的图片渲染。


总结🥇🥇


通过对懒加载的学习,使我更加对前端的性能优化有了更多的认识,并且还认识到,知识是相互的,因为在这里就用到了之前封装过的节流函数,因此我们在学习的时候要多总结,这样才能稳步提高。

相关文章
|
2月前
|
前端开发
后端返回图片二进制流,前端转base64
本文介绍了如何将后端返回的图片二进制流转换为Base64格式,以便在前端使用。通过在axios请求中设置`responseType`为`arraybuffer`,然后使用`btoa`和`Uint8Array`进行转换。
196 5
|
22天前
|
存储 前端开发 JavaScript
🚀前端轻松实现网页内容转换:一键复制、保存图片及生成 Markdown
在现代前端开发中,提升用户的交互体验至关重要。本文将详细介绍如何使用 HTML2Canvas 和 Turndown 两个强大的 JavaScript 库,实现将网页选中文本转化为图片并保存或复制到剪贴板,或将内容转换为 Markdown 格式。文章包含核心代码实现、技术细节和功能拓展方向,为开发者提供了一个轻量级的解决方案,提升用户体验。
113 68
|
27天前
|
JavaScript 前端开发 Python
django接收前端vue传输的formData图片数据
django接收前端vue传输的formData图片数据
26 4
|
26天前
|
前端开发 小程序 Java
java基础:map遍历使用;java使用 Patten 和Matches 进行正则匹配;后端传到前端展示图片三种情况,并保存到手机
这篇文章介绍了Java中Map的遍历方法、使用Pattern和matches进行正则表达式匹配,以及后端向前端传输图片并保存到手机的三种情况。
17 1
|
30天前
|
前端开发 JavaScript 编译器
不走弯路,纯前端如何把图片导出成视频!
【10月更文挑战第3天】不走弯路,纯前端如何把图片导出成视频!
38 3
|
30天前
|
JavaScript 前端开发 编译器
吐血整理:纯前端如何实现批量dom转图片,并下载成压缩包
【10月更文挑战第2天】吐血整理:纯前端如何实现批量dom转图片,并下载成压缩包
42 2
|
2月前
|
前端开发
前端之图片操作
前端之图片操作
|
2月前
|
前端开发 Windows
【前端web入门第一天】02 HTML图片标签 超链接标签 音频标签 视频标签
本文档详细介绍了HTML中的图片、超链接、音频和视频标签的使用方法。首先讲解了`&lt;img&gt;`标签的基本用法及其属性,包括如何使用相对路径和绝对路径。接着介绍了`&lt;a&gt;`标签,用于创建超链接,并展示了如何设置目标页面打开方式。最后,文档还涵盖了如何在网页中嵌入音频和视频文件,包括简化写法及常用属性。
48 13
|
2月前
|
前端开发 JavaScript
node接收前端上传的图片,单文件、多文件同name、多文件不同name
本文介绍了在Node.js中使用multer模块接收前端上传的图片,包括单文件上传、多文件上传(同name和不同name)以及任意类型文件上传的方法。
49 0
|
3月前
|
JavaScript 前端开发 编译器
纯前端如何实现批量dom转图片,并下载成压缩包
【8月更文挑战第22天】纯前端如何实现批量dom转图片,并下载成压缩包
86 0