Skip to content
文章目录

如何实现图片懒加载

思路及实现

  • 加载loading图片
  • 判断哪些图片要加载(滚动条以上scrollTop+当前内容clientHeight)
  • 替换真图片(将data-src中的值给到src,进行请求图片)

方案一: getBoundingClientRect()

Element.getBoundingClientRect() 方法返回元素的大小及其相对于视口的位置。

示例代码

js
// 定义图片懒加载处理函数
function mapImagesAndTryLoad() {
  // 获取所有含有 data-src属性的img标签
  const images = document.querySelectorAll('img[data-src]')
  if(images.length === 0) return

  images.forEach(img => {
    const rect = img.getBoundingClientRect()
    // 如果图片露出来 在视图范围内
    if(rect.top < window.innerHeight) {
      img.src = img.dataset.src
      // 移除 data-src属性,减少下次计算成本
      img.removeAttribute('data-src')
    }
  })
}
// "_.throttle()" 使用 节流提高性能 
window.addEventListener('scroll', _.throttle(() => {
  mapImagesAndTryLoad()
}, 100))

// 初始执行一次
mapImagesAndTryLoad()

方案二: IntersectionObserver API

IntersectionObserver API,一个能够监听元素是否到了当前视口的事件 entry.isIntersecting 代表目标元素可见

示例代码

js
const intersectionObserver = new IntersectionObserver((changes) => {
  // changes 目标集合
  changes.forEach(change => {
    // 判断元素是否在可见区域内
    if(change.isIntersectiong) {
      const img = change.target
      img.src = img.dataset.src
      // 停止监听
      intersectionObserver.unobserve(img)
    }
  })
})

function mapImagesAndTryLoad() {
  const images = document.querySelectorAll('img[data-src]')
  images.forEach(img => {
    // 开始监听目标元素
    intersectionObserver.observe(img)
  })
}

mapImagesAndTryLoad()

方案三 LazyLoading 属性

html
<img src="shanyue.jpg" loading="lazy" />