习题集——如何实现图片的懒加载?

591 阅读2分钟

什么是懒加载?

懒加载,顾名思义,就是在当前网页,滑动页面到图片出现在可见区域的时候再加载图片,所以问题就可分解为以下两方面:

  1. 如何判断图片出现在了可见区域
  2. 如何控制图片的加载

1.如何判断图片出现在了可见区域

可以监听window.scroll事件,通过clientTopoffsetTopclientHeight 以及 scrollTop 各种关于图片的高度作对比。

2.如何控制图片的加载

监听window.scroll 事件的过程中,当满足条件时动态设置<img>标签的src属性就可以了。


以上简要的介绍了实现的原理,不过具体实现的时候有很多可以优化的地方。

1.优化判断图片出现在了可见区域

引入了一个新的api,Element.getBoundingClientRect() 方法能快速返回元素的大小及其相对于视口的位置,拿页面上的body举例

console.log(document.body.getBoundingClientRect()); 
//DOMRect {
//  bottom: 0
//  height: 0
//  left: 0
//  right: 1920
//  top: 0
//  width: 1920
//  x: 0
//  y: 0
//}

2.优化window.scroll监听事件

加个节流器,提高性能。工作中一般使用lodash库里的 lodash.throttle 就可以了。(什么是节流?可见 什么是防抖和节流

3.同时优化判断图片出现在了可见区域和window.scroll监听事件

以上的思路我们可以看出主要过程是通过window.scroll 监听 Element.getBoundingClientRect() 并使用 lodash.throttle 节流。这一系列组合动作太复杂了,于是浏览器出了一个三合一事件: IntersectionObserver API,一个能够监听元素是否到了当前视口的事件,一步到位!事件回调的参数是 IntersectionObserverEntry 的集合,代表关于是否在可见视口的一系列值,其中change.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)

终究优化方案

浏览器觉得懒加载这事可以交给自己做,你们开发者加个属性就好了。

<img src="XXX.jpg" loading="lazy">

不过目前浏览器兼容性不太好,目前除了chrome几乎都不支持。