3

图片懒加载

一、使用 clientHeight、scrollTop 和 offsetTop

思路:获取视口高度和滚动轴的高度,和图片偏移高度对比,如果大于图片的偏移高度,则显示图片

代码

<body style="height:1900px">
  <h3>请往下拉</h3>
  <img
    src="default.jpg"
    data-src="1.png"
    style="position: absolute;top: 1200px;"
  />
</body>
// 1. 函数定义
let img = document.getElementsByTagName("img");
let num = img.length;
let count = 0; //计数器,从第一张图片开始计
function lazyload() {
  let viewHeight = document.documentElement.clientHeight; //视口高度
  let scrollTop = document.documentElement.scrollTop || document.body.scrollTop; //滚动条卷去的高度
  console.log(scrollTop, img[0].offsetTop);
  for (let i = count; i < num; i++) {
    // 元素现在已经出现在视口中
    if (img[i].offsetTop < scrollTop + viewHeight) {
      // 视口的高度大于元素的高度,表示已经下拉到可以看到图片的地方了
      if (img[i].getAttribute("src") !== "default.jpg") continue;
      img[i].src = img[i].getAttribute("data-src");
      count++;
    }
  }
}

// 2. 调用
lazyload(); //首次加载别忘了显示图片
window.addEventListener("scroll", lazyload);

最好对 scroll 事件做节流处理,以免频繁触发
参考防抖与节流

二、使用 getBoundingClientRect

原理

getBoundingClientRect API 获取当前客户页面浏览的高度,对比图片在窗口的高度,如果大于图片在窗口的高度,即可以显示图片了

主要代码

function lazyload() {
  for (let i = count; i < num; i++) {
    // 元素现在已经出现在视口中 客户视口高度大于图片高度
    if (
      img[i].getBoundingClientRect().top < document.documentElement.clientHeight
    ) {
      if (img[i].getAttribute("src") !== "default.jpg") continue;
      img[i].src = img[i].getAttribute("data-src");
      count++;
    }
  }
}

三、使用 IntersectionObserver

这是浏览器内置的一个 API,实现了监听 window 的 scroll 事件、判断是否在视口中以及节流三大功能

主要代码

// 1. 初始化IntersectionObserver,参数为具体的处理函数
const observer = new IntersectionObserver(changes => {
  //changes 是被观察的元素集合
  for (let i = 0, len = changes.length; i < len; i++) {
    let change = changes[i];
    // 通过这个属性判断是否在视口中
    if (change.isIntersecting) {
      const imgElement = change.target;
      imgElement.src = imgElement.getAttribute("data-src");
      observer.unobserve(imgElement); // 移除观察
    }
  }
});

// 2. 调用
let img = document.getElementsByTagName("img");
Array.from(img).forEach(item => observer.observe(item));
很方便地实现了图片懒加载,这个 IntersectionObserver 也可以用作其他资源的预加载,功能非常强大。

完整demo


zpfei
186 声望7 粉丝

往事如风~