一、懒加载介绍

懒加载原理: 图片进入可视区域之后再去请求图片资源

图片是在img标签有src属性才去加载的。

  • 懒加载的原理就是在图片进入可视化区域之后,动态的去设置img标签中的src属性。如果在可视区域之外的图片的img中的src属性已被提前设置,那么就不是懒加载了,而是所有图片都会被加载。
  • 在图片进入可视化区域之前,img标签上的src属性并没有被设置。在img标签上有一个data-url属性。该属性的值存放着图片的真实请求地址,但是由于src属性上并没有值,所以图片并不会被加载。我们的js可以监听scroll事件,在计算到图片进入可视区域之后。就拿到img标签上的data-url属性的值,把它设置到src属性上,这就是懒加载的一个原理。

图片懒加载的优势:

  • 对于电商等图片很多,页面很长的业务场景适用
  • 减少无效资源的加载:比如我们的页面有100张图片,但是用户往下滑动看的时候只看了十张图片。如果我们把这100张图片全部都加载完成,页面上会有很多的浪费。所以就可以使用懒加载,图片进入可视区域之后再去加载。
  • 并发加载的资源过多会阻塞js的加载,影响网站的正常使用。因为浏览器会限制在一个域名下并发请求的数量。如果前边图片加载数量过多,要发送http请求,就会影响到后边js的并发加载,影响到页面中js逻辑的使用(JS文件一般放在页面底部)。使用图片懒加载可以避免这个问题。

二、代码

使用一张loading图片占位

<img src="./img2/loading.jpg" class="lazyload-img" data-url="./img2/11.jpg">
<img src="./img2/loading.jpg" class="lazyload-img" data-url="./img2/12.jpg">
<img src="./img2/loading.jpg" class="lazyload-img" data-url="./img2/13.jpg">
<img src="./img2/loading.jpg" class="lazyload-img" data-url="./img2/14.jpg">
<img src="./img2/loading.jpg" class="lazyload-img" data-url="./img2/15.jpg">
<img src="./img2/loading.jpg" class="lazyload-img" data-url="./img2/16.jpg">
let viewport = document.documentElement;
let imgArr = [].slice.call(document.querySelectorAll('.lazyload-img'));

// 该函数用来判断某一个元素是否在可视区域
function isVisible(element) {
  let rect = element.getBoundingClientRect();
  // 用户不管是从上向下、从下向上、从左向右、从右向左滑动,都可以判断当前元素是否在可视区域
  return rect.top < viewport.clientHeight && rect.bottom > 0 && rect.left < viewport.clientWidth && rect.right > 0;
}

// 该函数动态设置图片的src属性,动态加载图片
function lazyloadImg() {
  for (let i = 0; i < imgArr.length; i++) {
    let img = imgArr[i];
    if (isVisible(img)) {
      img.src = img.getAttribute('data-url');
      imgArr.splice(i,1);
      i--;
    }
  }
}

// 一开始先执行一次,把在第一次进入页面时在可视区域的图片加载出来
lazyloadImg();

let timer = null;
document.addEventListener('scroll',function () {
  // 一个简单的防抖处理
  if (timer) clearTimeout(timer);
  timer = setTimeout(() => {
    // 页面滚动的时候,不断有新的图片进入可视区域,此时再调用lazyloadImg函数
    lazyloadImg();
  },100);
})

在这里插入图片描述

下面对上述JS代码进行解释:

1、document.documentElement

document.documentElement 属性返回当前文档的根元素节点(root)。HTML网页的该属性一般是<html>节点。

document.documentElement的clientHeight属性,返回当前视口的高度(即浏览器窗口的高度,不包括滚动条)。

document.documentElement的clientWidth属性,返回当前视口的宽度(即浏览器窗口的宽度,不包括滚动条)。

另外,window.innerHeightwindow.innerWidth 属性,也会返回网页在当前窗口中可见部分的高度和宽度,即“视口”(viewport)的大小(单位像素)。但是这两个属性值包括滚动条的高度和宽度。

2、getBoundingClientRect()

getBoundingClientRect方法(所有的元素结点上都有这个方法)返回一个对象,提供当前元素节点的大小、位置等信息,基本上就是 CSS 盒状模型的所有信息。

var rect = obj.getBoundingClientRect();

getBoundingClientRect方法返回的rect对象,具有以下属性(全部为只读)。

  • x:元素左上角相对于视口的横坐标
  • y:元素左上角相对于视口的纵坐标
  • height:元素高度
  • width:元素宽度
  • left:元素左上角相对于视口的横坐标,与x属性相等
  • right:元素右边界相对于视口的横坐标(等于x + width)
  • top:元素顶部相对于视口的纵坐标,与y属性相等
  • bottom:元素底部相对于视口的纵坐标(等于y + height)
    在这里插入图片描述
    由于元素相对于视口(viewport)的位置,会随着页面滚动变化,因此表示位置的四个属性值,都不是固定不变的。

注意,getBoundingClientRect方法的所有属性,都把边框(border属性)算作元素的一部分。也就是说,都是从边框外缘的各个点来计算。因此,width和height包括了元素本身 + padding + border。

前端学习交流QQ群,群内学习讨论的氛围很好,大佬云集,期待您的加入:862748629 点击加入

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐