图片懒加载

220 阅读4分钟

为什么要使用懒加载

懒加载也叫延迟加载指的是当需要用到该资源的时候才对其进行加载,是一种提升网页性能的方式。

懒加载可以提升用户体验,比如在我们浏览一个有大量图片的网页的时候如果一次性加载完所有的图片就会等待很长的时间,影响用户的体验,这样可能就会流失一部分客户,所以为了解决这个问题就引入了图片懒加载,当用户进入场景的时候先加载第一屏的图片(也可以再多一点),然后当用户向下滚动的时候再加载后面对应的一页中的图片,这样,如果用户看了几页不想看了,后边的图片就不用加载了,减轻了服务器的压力。相应的首屏展示也更快了。

从中可以看出懒加载的优点:

  • 缩短首屏加载时间,提升用户体验。
  • 减轻服务器压力,更具用户需求加载,不用全部加载

懒加载应用十分广泛,比如淘宝只会加载第一屏的图片,如果用户需要浏览后面的图片再进行加载。当你快速把滚动条拖到最后你会发现图片并没有加载完成。

懒加载实现原理

懒加载的基本思路就是不给imgsrc属性,把图片地址写在data-src中,当需要加载该图片时再把data-src中的值写到src中。

如何判断是否需要加载?

判断图片顶部距离页面顶部的距离是否小于页面的高度,即当图片进入可视区域的时候就加载该图片

获取图片距离页面顶部距离

使用API接口:el.getBoundingClientRect(),它会返回一个DOMRect对象,DOMRect 对象包含了一组用于描述边框的只读属性——lefttoprightbottom,单位为像素。除了 widthheight 外的属性都是相对于视口的左上角位置而言的。

这样我们就可以通过DOMRect对象的top属性来获取图片距离页面顶部距离。

代码实现

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
  <style>
    .image-item {
      display: block;
      margin-bottom: 50px;
      height: 400px;
      width: 400px;
      background-color: #cccccc;
    }
  </style>
</head>

<body>
  <img src="" alt="" class="image-item" data-src="./imgs/0.jpg">
  <img src="" alt="" class="image-item" data-src="./imgs/1.jpg">
  <img src="" alt="" class="image-item" data-src="./imgs/2.jpg">
  <img src="" alt="" class="image-item" data-src="./imgs/3.jpg">
  <img src="" alt="" class="image-item" data-src="./imgs/4.jpg">
  <img src="" alt="" class="image-item" data-src="./imgs/5.jpg">
  <img src="" alt="" class="image-item" data-src="./imgs/6.jpg">
  <img src="" alt="" class="image-item" data-src="./imgs/7.jpg">
  <img src="" alt="" class="image-item" data-src="./imgs/8.jpg">
  <img src="" alt="" class="image-item" data-src="./imgs/9.jpg">
  <img src="" alt="" class="image-item" data-src="./imgs/10.jpg">
  <img src="" alt="" class="image-item" data-src="./imgs/11.jpg">
  <script>
    let viewHeight = document.documentElement.clientHeight || document.body.clientHeight
    let imgs = document.querySelectorAll("img[data-src]")
    imgs = [...imgs]
    imgs.forEach(item => {
      lazy(item)
    })
    function lazy(item) {
      let itemTop = item.getBoundingClientRect().top
      if (itemTop < viewHeight && itemTop > 0) {
        let src = item.getAttribute("data-src")
        item.setAttribute("src", src)
        item.classList.add("show")
      }  
      if (itemTop > viewHeight && item < 0) {
        item.removeAttribute("src")
      }
    }
    
    window.addEventListener("scroll", function () {
      imgs.forEach(item => {
        lazy(item)
      })
    })
  </script>
</body>

</html>

这样就实现了一个简单的懒加载,但是我们发现在滚动滚动条的时候只要图片进入可视区域就立即加载了,我们希望可以在我们停止滚动一段时间后才加载,所以这里我们需要防抖函数来控制。

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
  <style>
    .image-item {
      display: block;
      margin-bottom: 50px;
      height: 400px;
      width: 400px;
      background-color: #cccccc;
    }
    .image-item.show {
      animation: show 1s linear;
    }
    @keyframes show {
      0% {filter: blur(3px)}
      30% {filter: blur(1px)}
      100% {filter: blur(0px)}
    }
  </style>
</head>

<body>
  <img src="" alt="" class="image-item" data-src="./imgs/0.jpg">
  <img src="" alt="" class="image-item" data-src="./imgs/1.jpg">
  <img src="" alt="" class="image-item" data-src="./imgs/2.jpg">
  <img src="" alt="" class="image-item" data-src="./imgs/3.jpg">
  <img src="" alt="" class="image-item" data-src="./imgs/4.jpg">
  <img src="" alt="" class="image-item" data-src="./imgs/5.jpg">
  <img src="" alt="" class="image-item" data-src="./imgs/6.jpg">
  <img src="" alt="" class="image-item" data-src="./imgs/7.jpg">
  <img src="" alt="" class="image-item" data-src="./imgs/8.jpg">
  <img src="" alt="" class="image-item" data-src="./imgs/9.jpg">
  <img src="" alt="" class="image-item" data-src="./imgs/10.jpg">
  <img src="" alt="" class="image-item" data-src="./imgs/11.jpg">
  <script>
    let debounce = function (fn, wait, immedate = false) {
      let timer = null
      return function (...arg) {
        if (immedate) {
          fn.apply(this, arg)
          immedate = false
        }
        timer ? clearTimeout(timer) : ''
        timer = setTimeout(() => {
          fn.apply(this)
        }, wait);
      }
    }
    let viewHeight = document.documentElement.clientHeight || document.body.clientHeight
    let imgs = document.querySelectorAll("img[data-src]")
    imgs = [...imgs]
    imgs.forEach(item => {
      lazy(item)
    })
    function lazy(item) {
      let itemTop = item.getBoundingClientRect().top
      if (itemTop < viewHeight && itemTop > 0) {
        let src = item.getAttribute("data-src")
        item.setAttribute("src", src)
        item.classList.add("show")
      }  
      if (itemTop > viewHeight && item < 0) {
        item.removeAttribute("src")
      }
    }
    window.addEventListener("scroll", debounce(function () {
      imgs.forEach(item => lazy(item))
    }, 100, false))
  </script>
</body>

</html>

上面我们还添加了一点动画,让图片出现的不那么突兀。

到这里就全部讲完啦,写文章不容易希望各位小哥哥、小姐姐、大佬们点个赞吧。