图片懒加载实现方案

方案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,请尝试更新或者使用其他主流浏览器。");
  }
 });
方案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);
方案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');
    }
    // 图片全部加载完毕,移除滚动事件
    if (i === imgs.length-1) 
    	document.removeEventListener('scroll', lazyLoad)
  };
}
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)();

上述方法的测试实例为

<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>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值