Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

【Q001】网站开发中,如何实现图片的懒加载 #1

Open
shfshanyue opened this issue Nov 1, 2019 · 2 comments
Labels

Comments

@shfshanyue
Copy link
Owner

@shfshanyue shfshanyue commented Nov 1, 2019

网站开发中,如何实现图片的懒加载,随着 web 技术的发展,他有没有一些更好的方案

@shfshanyue shfshanyue added the html label Nov 2, 2019
@shfshanyue

This comment has been minimized.

Copy link
Owner Author

@shfshanyue shfshanyue commented Nov 3, 2019

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

故问题拆分成两个:

  1. 如何判断图片出现在了当前视口 (即如何判断我们能够看到图片)
  2. 如何控制图片的加载

方案一

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

clientTopoffsetTopclientHeight 以及 scrollTop 各种关于图片的高度作比对

这些高度都代表了什么意思?

这我以前有可能是知道的,那时候我比较单纯,喜欢死磕。我现在想通了,背不过的东西就不要背了

所以它有一个问题:复杂琐碎不好理解!

仅仅知道它静态的高度还不够,我们还需要知道动态的

如何动态?监听 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!

@zhaoguangyue

This comment has been minimized.

Copy link

@zhaoguangyue zhaoguangyue commented Nov 22, 2019

兼容性
方案1:all
方案2:all
方案3:ie不支持
方案4: 除chrome几乎都不支持

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
2 participants
You can’t perform that action at this time.