• 图片懒加载实现方案


    方案1:使用IntersectionObserver对象
    document.addEventListener("DOMContentLoaded", () => {
      if ("IntersectionObserver" in window) {
        const imgs = document.getElementsByTagName("img");
        const imageObserve = new IntersectionObserver((entries) => {
          entries.forEach((entry) => {
            // 通过该属性判断元素是否出现在视口内
            if (entry.isIntersecting) {
              // entry.target能够取得那个dom元素
              const img = entry.target;
              img.src = img.dataset.src;
              // 图片加载完成后解除监听
              imageObserve.unobserve(img);
            }
          });
        });
        [...imgs].forEach((img) => {
          // 将所有的图片加入监听
          imageObserve.observe(img);
        });
      } else {
        alert("您的浏览器尚不支持IntersectionObserver,请尝试更新或者使用其他主流浏览器。");
      }
     });
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    方案2:通过原生获取元素位置(offsetTop | scrollHeight),当出现到可视区域加载

    window.innerHeight:浏览器可视窗口的高度
    document.documentElement.scrollTop:可视窗口滚动过的距离
    元素.offsetTop:元素相对于其父元素的顶部内边距的距离
    元素.offsetHeight:元素的像素高度

    const imgs = document.getElementsByTagName('img');
    function throttle(fn, delay) {
      let timer = null;
      return function() {
        let arg = arguments;
        let _this = this;
        if (!timer) {
          timer = setTimeout(() => {
            fn.apply(_this, arg);
          }, delay)
        }
      }
    }
    function lazyLoad(imgs) {
      // 浏览器可视窗口的高度;
      const windowHeight = window.innerHeight;
      // 可视窗口滚动过的距离;
      const scrollHeight = document.documentElement.scrollTop;
      for (let i = 0; i < imgs.length; i++) {
        // !imgs[i].src 是当该图片已加载好之后,无需重复加载
        if (
          windowHeight + scrollHeight > imgs[i].offsetTop
          && !imgs[i].src
          && imgs[i].offsetTop + imgs[i].offsetHeight > scrollHeight
        ){
          imgs[i].src = imgs[i].dataset.src;
        }
      }
    };
    // 进入页面时执行一次加载;
    lazyLoad(imgs);
    // 监听滚动事件,进行图片懒加载;
    window.onscroll = () => throttle(lazyLoad, 300)(imgs);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    方案3:getBoundingClientRect

    和方案2大同小异,只是浏览器提供了getBoundingClientRect这个方法,是的计算更加方便了。

    const imgs = document.getElementsByTagName('img');
    function isInViewport(element) {
      const rect = element.getBoundingClientRect();
      return rect.bottom > 0 &&
        rect.right > 0 &&
        rect.left < (window.innerWidth || document.documentElement.clientWidth) &&
        rect.top < (window.innerHeight || document.documentElement.clientHeight);
    }
    function lazyLoad() {
        for (let i = 0; i < imgs.length; i++) {
          console.log(imgs[i])
        if (!imgs[i].src && isInViewport(imgs[i])) {
          imgs[i].src = imgs[i].dataset.src;
          imgs[i].removeAttribute('data-src');
        }
      };
    }
    function throttle(fn, delay) {
      let timer = null;
      return function() {
        let arg = arguments;
        let _this = this;
        if (!timer) {
          timer = setTimeout(() => {
            fn.apply(_this, arg);
          }, delay)
        }
      }
    }
    lazyLoad();
    // 监听滚动事件,进行图片懒加载;
    window.onscroll = () => throttle(lazyLoad, 300)();
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32

    上述方法的测试实例为

    <div>
      <img data-src="https://p1-q.mafengwo.net/s9/M00/CB/E6/wKgBs1hSPKiAXvE9ABIa6R4tA3U20.jpeg?imageView2%2F2%2Fw%2F1360%2Fq%2F90" />
      <img data-src="https://lu17996.com/ueditor/php/upload/image/20220316/1647419221190368.jpeg" />
      <img data-src="https://5b0988e595225.cdn.sohucs.com/images/20190131/80e42b7874f746cb8b8d08b9f82de959.jpeg" />
      <img data-src="https://p8.itc.cn/q_70/images03/20230721/54943164094b4f27b98189aceb264a00.jpeg" />
      <img data-src="https://p26-sign.bdxiguaimg.com/tos-cn-p-0015/o0JQgDsH9OfIkAJbjH4kUZeOv8ynAB8mCmiAU3~tplv-pk90l89vgd-crop-center:1280:720.jpeg?x-expires=1705285977&x-signature=LrTgp%2Fkyk0j3i4TNMFzEPexO5BI%3D" />
      <img data-src="https://p5.itc.cn/images01/20210401/2df3cac26bec4838998a9a122df2cd0b.jpeg" />
    div>
    <style>
    img {
      height: 100vh;
      display: block;
      margin-bottom: 50px;
    }
    style>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
  • 相关阅读:
    物联网AI MicroPython传感器学习 之 Relay继电器模块
    2022 APMCM亚太数学建模竞赛 C题 全球是否变暖 问题二python代码实现(更新完毕)
    吴恩达深度学习笔记(二)——浅层神经网络
    SpringSecurity - 启动流程分析(五)
    如何保证接口的幂等性?
    【PAT甲级 - C++题解】1076 Forwards on Weibo
    联想集团:长期前景稳定,业务转型正在提高盈利能力
    MySql 各种 join
    Java基础异常处理
    SAP 输出管理:生成自定义发票文件
  • 原文地址:https://blog.csdn.net/zhongqw_00/article/details/134449675