前端懒加载原理实现

1,282 阅读1分钟

为什么需要懒加载?

我们在开发中经常会遇到需要展示大量数据的需求,此时如果我们一次性加载所有数据的话,长时间的等待页体验是非常差的。况且可能用户也不需要看到网页上所有的东西,此时就造成了资源浪费。

懒加载是什么?

懒加载说白了就是一种前端优化手段,通过将数据分片,每次请求一部分数据,来减少页面加载时间,同时也能让用户判断是否需要继续看接下来的内容,避免不必要的资源浪费。

懒加载实现

这里依据实现原理写了一个简单的demo.

<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <style>
    img {
      display: block;
      width: 100%;
      min-height: 500px;
    }
  </style>
  <body>
    <div>
      <img data-src="./img/测试图片/1.jpg" alt="" />
      <img data-src="./img/测试图片/2.jpg" alt="" />
      <img data-src="./img/测试图片/img_1.jpg" alt="" />
      <img data-src="./img/测试图片/img_2.jpg" alt="" />
      <img data-src="./img/测试图片/img_3.jpg" alt="" />
      <img data-src="./img/测试图片/po.jpg" alt="" />
      <img data-src="./img/测试图片/yz.jpg" alt="" />
      <img data-src="./img/测试图片/大作.jpg" alt="" />
      <img data-src="./img/测试图片/少司命.jpg" alt="" />
      <img data-src="./img/测试图片/张良.jpg" alt="" />
      <img data-src="./img/测试图片/焰灵姬.jpg" alt="" />
      <img data-src="./img/测试图片/田言.jpg" alt="" />
      <img data-src="./img/测试图片/风景.jpg" alt="" />
    </div>
    <script>
      let imgs = document.querySelectorAll("img");

      // offsetTop 指的是子元素到起其直接父元素的头部距离 此处定义一个方法找到其到body的距离
      const getTop = (e) => {
        let top = e.offsetTop;
        while ((e = e.offsetParent)) {
          top += e.offsetTop;
        }
        return top;
      };

      // 懒加载核心代码
      const lazyLoad = (e) => {
        let H = document.documentElement.clientHeight;
        let S = document.documentElement.scrollTop || document.body.scrollTop;
        imgs.forEach((item, index) => {
          if (H + S + 20 >= getTop(item) && !item.src) { // 此处增加判断,没有加src属性的元素才会执行此操作,避免重复赋值
            item.src = item.getAttribute("data-src");
          }
        });
      };

      window.onload = window.onscroll = () => lazyLoad(imgs);
    </script>
  </body>
</html>

当然,我们最后还需要用节流函数(throttle)来做优化,避免事件触发太多次。 除此之外还可以用现成的api(IntersectionObserver)去帮助监听元素是否出现在视口中,可以省去判断环节,但我试了下,貌似ie兼容不太好···