关于javascript:前端懒加载和预加载

44次阅读

共计 4434 个字符,预计需要花费 12 分钟才能阅读完成。

懒加载和预加载的目标都是为了进步用户的体验,二者行为是相同的,一个是提早加载,另一个是提前加载。懒加载对缓解服务器压力有肯定作用,预加载则会增长服务器前端压力缓存。

懒加载 lazyload

懒加载:又叫提早加载、按需加载,当咱们关上一个网页,优先展现的首屏图片就先加载,而其余的图片,等到须要去展现的时候再去申请图片资源。

目标 :更好的加载页面的 首屏 内容,对于含有不少图片的比拟长的网页来讲,可能加载的更快,防止了首次关上时,一次性加载过多图片资源,是对网页性能的一种优化形式。

原理:浏览器解析到 img 标签的 src 有值,才会去发动申请,那么就能够让图片须要展现时,才对其 src 赋值真正的图片地址。

实现代码

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset=UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title> 图片懒加载 </title>
    <style>
      * {
        margin: 0;
        padding: 0;
      }
      img {
        margin: 50px;
        width: 400px;
        height: 200px;
      }
    </style>
  </head>
  <body>
    <div class="img-container">
      <img
        src="loading.gif"
        alt=""data-src="1.jpg"class="lazyload"
      />
    </div>
    <div class="img-container">
      <img
        src="loading.gif"
        alt=""data-src="2.jpg"class="lazyload"
      />
    </div>
    <div class="img-container">
      <img
        src="loading.gif"
        alt=""data-src="3.jpg"class="lazyload"
      />
    </div>
    <div class="img-container">
      <img
        src="loading.gif"
        alt=""data-src="4.jpg"class="lazyload"
      />
    </div>
    <div class="img-container">
      <img
        src="loading.gif"
        alt=""data-src="5.jpg"class="lazyload"
      />
    </div>
​
    <script>
      const imgs = [...document.querySelectorAll(".lazyload")]; //img 元素转换成数组
      lazyload();  // 初始调用一次
      window.addEventListener("scroll", lazyload, false);  // 监听滚动时也调用 lazyload 函数,冒泡阶段
      // 懒加载
      function lazyload() {for (let i = 0; i < imgs.length; i++) {const $img = imgs[i];          // 每次循环拿到每一个 img 元素
          if (isInVisibleArea($img)) {   // 判断 img 元素是否在可视区域内
            $img.src = $img.dataset.src; // 用 data-src 替换 src 属性
            imgs.splice(i, 1);           // 对应该索引的元素删掉
            i--;  
          }
        }
      }
      // 判断 DOM 元素是否在可视区域内,返回 true/false
      function isInVisibleArea($el) {const rect = $el.getBoundingClientRect();
        console.log(rect);
        return rect.bottom > 0 && rect.top < window.innerHeight && rect.right > 0 && rect.left < window.innerWidth;
      }
    </script>
  </body>
</html>

实现细节

1 如何加载图片

用 img 的 data-src 属性寄存真正须要显示的图片的门路,当页面滚动直到图片呈现在可视区域时,将 data-src 中的图片地址值赋值给 src 属性值。

2 如何判断一个元素呈现在可视区域

监听滚动事件,用 getBoundingClientRect() 获取 DOM 元素在页面的地位,该函数返回 rect 对象,如下图所示,如果 rect.bottom 为正数,rect.top大于页面高度,或者 rect.right 为正数,或者 rect.left 大于页面宽度,则认为元素已不在页面的可视区域。

const rect = element.getBoundingClientRect();
  • rect.top:元素上边到视窗上边的间隔;
  • rect.bottom:元素下边到视窗上边的间隔;
  • rect.left:元素右边到视窗右边的间隔;
  • rect.right:元素左边到视窗右边的间隔;
  • window.innerHeight:视窗高度
  • window.innerWidth:视窗宽度

实现成果

利用开发者工具咱们能够看到如下截图:

  • 最后关上页面:只显示前两张图片,前面三张图片还没有呈现在以后页面

因为前面三张还没有呈现,那么就放弃 loading.gif,这样就节俭了加载的工夫,当咱们持续滚动直到呈现页面底部,通过开发者工具看到如下的截图:

预加载 preload

预加载 提前加载 所须要的图片资源,加载结束后会 缓存到本地 ,当须要时能够 立即显示 进去。

目标 :看完一张图片,再看下一张时,会有一段空白的加载工夫,如果网络不是很好,加载的工夫就会比拟久,预加载能够让用户 无需期待,取得间接预览的良好体验。

利用场景:看漫画时,如果咱们看完 2 了,想看 33 却还没加载完就会大大降低体验感,而如果能在咱们预览 2 这段时间里就提前加载好 3,等到咱们看 3 时就间接外面显示。那么就体验会好很多。参考视频解说:进入学习

实现办法

1 通过 CSS

步骤

  • 创立用来预加载的标签
  • 给标签应用背景图,背景图的门路是须要预加载的图片资源,并将图片移到看不见的中央,或放大到看不见。
  • 当应用到曾经预加载好的图片时,会间接应用缓存好的图片资源,而不须要向服务器发送申请。
<!DOCTYPE html>
<html lang="en">
<head>
 <meta charset="UTF-8">
  <title>CSS 预加载 </title>
  <style>
    ul,li{ 
      padding:0;
      margin:0;
      list-style:none;
    }
    img {width: 300px;}
    #preImg1 {background-image: url('1.jpg');
      width: 0;
      height: 0;  /* 暗藏用来预加载的标签 */
    }
    #preImg2 {background-image: url('2.jpg');
      width: 0;
      height: 0;
    }
    #preImg3 {background-image: url('3.jpg');
      width: 0;
      height: 0;
    }
  </style>
</head>
<body>
  <button onclick="show()"> 点击显示图片 </button>
  <ul>
    <li id="preImg1"/>
    <li id="preImg2"/>
    <li id="preImg3"/>
  </ul>
</body>
<script>
  const show = function () {document.querySelector("ul").innerHTML = `
      <li><img src="1.jpg"></li>
      <li><img src="2.jpg"></li>
      <li><img src="3.jpg"></li>`
  }
</script>
</html>

2 通过 JavaScript

步骤

  • 将须要预加载的图片资源的 URL 保留在数组里
  • 循环遍历 URL 数组执行以下步骤,直到完结
  • 创立一个 image 对象 new Image()
  • 将 image 对象的 src 属性的值指定为预加载图片的 URL
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title> 图片预加载 </title>
    <style>
      .img-container {
        display: flex;
        align-items: center;
        height: 100vh;
        background-color: rgba(0, 0, 0, 0.5);
      }
      img {width: 100%;}
      * {
        margin: 0;
        padding: 0;
      }
    </style>
  </head>
  <body>
    <div class="img-container">
      <img src="1.jpg" alt=""id="img" />
    </div>

    <script>
      const imgs = [
        "2.jpg",
        "3.jpg",
        "4.jpg",
        "5.jpg",
      ];
      let i = 0;
      const $img = document.getElementById("img");

      // 页面一开始调用 preload,加载数组的第一个元素
      preload(imgs[i])
        .then((data) => {})
        .catch(() => {});

      // 点击切换
      $img.addEventListener(
        "click",
        () => {if (i < imgs.length) {$img.src = imgs[i];  // 将数组元素的 src 赋值给页面元素
            i++;
            if (i < imgs.length) {preload(imgs[i]);  // 当索引小于数组 length,预加载下一个图片
            }
          } else {console.log("曾经是最初一张了!");  // 当 索引和 数组 length 雷同 则数组内没元素了
          }
        },
        false
      );

      // 预加载
      function preload(src) {return new Promise((resolve, reject) => {const image = new Image();  // 创立一个新的图片标签
          image.addEventListener("load", () => resolve(image), false);  // 图片加载实现调用胜利状态
          image.addEventListener("error", () => reject(), false);   // 图片加载失败调用失败状态
          image.src = src;  // 将传进来的 src 赋值给新的图片
        });
      }
    </script>
  </body>
</html>

实现成果

总结比照

懒加载 预加载
定义 提早加载、按需加载 提前加载、不须要也提前加载
目标 更好更快地加载页面 首屏 内容,网页性能优化 让用户 无需期待,取得间接预览的良好体验
毛病 须要监听图片是否显示,消耗浏览器性能 占用较多的后盾资源,可能一次性加载较多的图片
利用场景 电商搜寻产品时图片展现 观看漫画时,每次切换的下一张图片提前加载

正文完
 0