Skip to content

图片懒加载

  1. 实现原理:当访问一个页面的时候,先把 img 元素或是其他元素的背景图片路径替换成一张大小为 1*1px 图片的路径(这样就只需请求一次),当图片出现在浏览器的可视区域内时,才设置图片真正的路径,让图片显示出来。

  2. 实现方法:先把图片路径放在 data-src 中,到达可视窗口才把它放进 src

监听滑动,判断是否进入视口

getBoundingClientRect().top 能拿到元素距离可视区域最高边的距离差

js
const imgs = document.getElementsByTagName('img')

function isEntry(e){ // 判断是否进入可视区域
    const clientHeight = document.documentElement.clientHeight || document.body.clientHeight
    const bound = e.getBoundingClientRect()
    return bound.top <= clientHeight
}

function lazyLoadImgs(){ // 进入可视区域的图片进行加载
    Array.from(imgs).forEach(img => {
    	if(isEntry(img)){
            img.src = img.getAttribute('data-src')
        }  
    })
}

lazyLoadImgs() // 开始先执行一遍,把在显示区域的图片加载了
window.scroll = function(){
    lazyLoadImgs() // 滚动在判断加载,这里感觉可以加个节流去优化
}

IntersectionObserver

js
function lazyLoad(imgs) {
  const io = new IntersectionObserver((ioes) => {
    // 进入、退出视口的元素
    ioes.forEach((ioe) => {
      const img = ioe.target
      const isIntersectionRatio = ioe.intersectionRatio > 0 && ioe.intersectionRatio <= 1
      // 如果是进入视口,且没有 src
      if (isIntersectionRatio && !img.src) {
        img.src = img.dataset.src
      }
      img.onerror = img.onload = () => io.unobserve(img)
    })
  })
  imgs.forEach(img => io.observe(img))
}

const imgs = document.getElementsByTagName('img')
lazyLoad(imgs)