实现图片懒加载的几种方案比较

懒加载,顾名思义,在当前网页,滑动页面到能看到图片的时候再加载图片javascript

故问题拆分红两个:html

  1. 如何判断图片出如今了当前视口 (即如何判断咱们可以看到图片)
  2. 如何控制图片的加载

本篇文章原文地址: 如何实现图片懒加载,另存到 个人每日一题,欢迎 starjava

方案一

如何判断图片出如今了当前视口

clientTopoffsetTopclientHeight 以及 scrollTop 各类关于图片的高度做比对git

这些高度都表明了什么意思?程序员

这我之前有多是知道的,那时候我比较单纯,喜欢死磕。我如今想通了,背不过的东西就不要背了github

因此它有一个问题:复杂琐碎很差理解!web

仅仅知道它静态的高度还不够,咱们还须要知道动态的面试

如何动态?监听 window.scroll 事件后端

如何控制图片的加载

<img data-src="shanyue.jpg">
复制代码

首先设置一个临时属性 data-src,控制加载时使用 src 代替 data-src浏览器

方案二

改进一下

如何判断图片出如今了当前视口

引入一个新的 API, Element.getBoundingClientRect() 方法返回元素的大小及其相对于视口的位置。

getBoundingClientRect示例图

那如何判断图片出如今了当前视口呢,根据示例图示意,代码以下,这个就比较好理解了,就能够很容易地背会(就能够愉快地去面试了)。

// clientHeight 表明当前视口的高度
img.getBoundingClientRect().top < document.documentElement.clientHeight
复制代码

监听 window.scroll 事件也优化一下

加个节流器,提升性能。工做中通常使用 lodash.throttle 就能够了,万能的 lodash 啊!

_.throttle(func, [wait=0], [options={}])
复制代码

参考 什么是防抖和节流,他们的应用场景有哪些

方案三

再改进一下

如何判断图片出如今了当前视口

方案二使用的方法是: window.scroll 监听 Element.getBoundingClientRect() 并使用 _.throttle 节流

一系列组合动做太复杂了,因而浏览器出了一个三合一事件: IntersectionObserver API,一个可以监听元素是否到了当前视口的事件,一步到位!

事件回调的参数是 IntersectionObserverEntry 的集合,表明关因而否在可见视口的一系列值

其中,entry.isIntersecting 表明目标元素可见

const observer = new IntersectionObserver((changes) => {
  // changes: 目标元素集合
  changes.forEach((change) => {
    // intersectionRatio
    if (change.isIntersecting) {
      const img = change.target
      img.src = img.dataset.src
      observer.unobserve(img)
    }
  })
})

observer.observe(img)
复制代码

固然,IntersectionObserver 除了给图片作懒加载外,还能够对单页应用资源作预加载。

如在 next.js v9 中,会对视口内的资源作预加载,能够参考 next 9 production optimizations

<Link href="/about">
  <a>关于山月</a>
</Link>
复制代码

方案四

浏览器以为懒加载这事能够交给本身作,大家开发者加个属性就行了。实在是...!

<img src="shanyue.jpg" loading="lazy">
复制代码

不过目前浏览器兼容性不太好,关于 loading 属性的文章也能够查看 Native image lazy-loading for the web!

总结

总结一下

  • window.scroll 监听各类 topheight 并使用 _.throttle 节流,可是很差理解各类 tophegith
  • window.scroll 监听 getBoundingClientRect 并使用 _.throttle 节流,没有一个统一事件,相对复杂
  • IntersectionObserver,浏览器推出了一个事件,方便简单
  • img.loading=lazy,浏览器直接给你解决,开发者直接标注属性

更多问题


我是山月,一个喜欢跑步与登山的程序员,我会按期分享全栈文章在我的公众号中,欢迎交流

欢迎关注公众号山月行,我会按期分享一些先后端以及运维的文章