Image lazy loading (three ways)

The first way:

<!DOCTYPE html>
<html lang="en">
<head>
   <meta charset="UTF-8">
   <meta name="viewport" content="width=device-width, initial-scale=1.0">
   <title>Document</title>
   <style>
       .imgs{
           display: flex;
           flex-direction: column;
           text-align: center;
           width: 500px;
       }
       .img-item{
           height:600px;
           width: 400px;
           margin: 10px;
       }
   </style>
</head>
<body>
   <div class="imgs">
       <img data-src="imgs/1.jpg" alt="loading" class="img-item">
       <img data-src="imgs/2.jpg" alt="loading" class="img-item">
       <img data-src="imgs/3.jpg" alt="loading" class="img-item">
       <img data-src="imgs/4.jpg" alt="loading" class="img-item">
       <img data-src="imgs/5.jpg" alt="loading" class="img-item">
       <img data-src="imgs/6.jpg" alt="loading" class="img-item">
       <img data-src="imgs/7.jpg" alt="loading" class="img-item">
       <img data-src="imgs/8.jpg" alt="loading" class="img-item">
       <img data-src="imgs/9.jpg" alt="loading" class="img-item">
       <img data-src="imgs/10.jpg" alt="loading" class="img-item">
       <img data-src="imgs/11.jpg" alt="loading" class="img-item">
       <img data-src="imgs/12.jpg" alt="loading" class="img-item">
       <img data-src="imgs/13.jpg" alt="loading" class="img-item">

   </div>
</body>
<script>
     let imgs = document.querySelectorAll('img');
       let lazyload = function(){
           let scrollTop = document.body.scrollTop || document.documentElement.scrollTop; 	//获取浏览器滚动高度
           let height = window.innerHeight; 	//获取浏览器可视高度
           for(let i=0;i < imgs.length;i++){
               //如果元素距离文档顶部的高度小于浏览器的滚动高度加浏览器的可视高度,则需要加载
               if(imgs[i].offsetTop < scrollTop + height ){	  //imgs[i].offsetTop 距离文档顶部的高度
               //性能优化 进行判断 已经加载的不会再进行加载
	               if(imgs[i].alt != 'loaded'){
	                   imgs[i].src = imgs[i].getAttribute('data-src'); //将data-src属性值赋值给src
	                   imgs[i].alt = 'loaded'
	               }
               }
           }
       }
       //调用懒加载函数,加一个防抖函数
       function throttle(method,delay){
          let timer = null;
           return function(){
               clearTimeout(timer);
               timer=setTimeout(function(){
                   method()
               },delay);
           }
       }
       window.onscroll = throttle(lazyload,200);
</script>
</html>

The second way:

The second method is actually similar to the first method, except that the method of calculating whether the image is in the visible area is different, and the repeated part is omitted, as follows:

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();

The third method (excellent):
In fact, the above two methods have roughly achieved lazy loading, but they all have a disadvantage, that is, when a scroll event occurs, a large number of loops and judgment operations occur to determine whether the image is visible or not inside. This is naturally not very good, so is there a workaround. Here we introduce an observer interface called Intersection Observer, which is a constructor provided by the browser natively, and using it can save a lot of loops and judgments. Of course, its compatibility may not be very good, depending on the situation.

What is Intersection Observer? The function of this constructor is that it can observe the intersection area between the visible window and the target element. To put it simply, when we use it to observe our picture, when the picture appears or disappears in the visible window, it can know and execute a special callback function, and we use this callback function to realize our operation. The concept is boring and difficult to understand, just look at the following example:
 

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);
      }

Guess you like

Origin blog.csdn.net/qq_39339179/article/details/130701806