图片懒加载

146 阅读1分钟

「这是我参与2022首次更文挑战的第19天,活动详情查看:2022首次更文挑战

前言

之所以使用图片懒加载是因为当初始化某个页面的时候如果图片很多就会并发去请求,这是非常消耗性能的,有可能导致页面加载时间过长,给用户的体验非常的不好。使用图片懒加载的好处大致可分为以下三点

  • 减少不必要的资源加载(以为可视区外的图片用户可能始终都不会看到,他压根就不往下翻动页面),这可以减少服务器的压力,也减少浏览器的压力。
  • 防止图片加载过多阻塞js的加载,影响网页的加载速度
  • 提升用户的使用体验

懒加载的思路

懒加载的思路总结为一句话就是当图片到达可视区的时候再去加载图片。具体步骤如下

  • 首先获取到所有的img元素
  • 通过循环来判断每个img元素是否在可视区内
  • 如果在可视区内就给img的src属性设置图片地址
  • 绑定鼠标滚动事件,监听鼠标的滚动

代码实现

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        div {
            height: 400px;
            border: 1px solid #ccc;
        }
        img {
            height: 100%;
        }
    </style>
</head>

<body>
    <div><img src="" data-src="./img/1.jpg" alt=""></div>
    <div><img src="" data-src="./img/2.png" alt=""></div>
    <div><img src="" data-src="./img/3.jpg" alt=""></div>
    <div><img src="" data-src="./img/4.png" alt=""></div>
    <div><img src="" data-src="./img/5.webp" alt=""></div>
    <div><img src="" data-src="./img/6.png" alt=""></div>
    <div><img src="" data-src="./img/7.png" alt=""></div>
    <div><img src="" data-src="./img/8.png" alt=""></div>
    <script>
        let imgList = [...document.querySelectorAll('img')]
        let length = imgList.length
        //在这里imgLazyLoad函数也可以写成自运行函数的形式
        const imgLazyLoad = function () {
            let count = 0

            return function () {
                let deleteIndexList = []
                imgList.forEach((img, index) => {
                    //getBoundingClientRect()方法是用来获取元素的大小以及其相对于视口的位置
                    let rect = img.getBoundingClientRect()
                    //这里的document.documentElement.clientHeight是获取可视区的高度,也可以用window.innerHeight,它们两者的区别是后者包含横向滚动条的高度,前者不包含横向滚动条的高度
                    if (rect.top < document.documentElement.clientHeight) {
                        img.src = img.dataset.src
                        deleteIndexList.push(index)
                        count++
                        //这里做的处理是当所有图片都加载完毕后删除监听时间
                        if (count === length) {
                            document.removeEventListener('scroll', imgLazyLoad())
                        }
                    }
                })
                //这里的作用是把已经加载了的图片从imgList中删除,减少循环的次数,提升性能
                imgList = imgList.filter((img, index) => !deleteIndexList.includes(index))
            }

        }

        // 在这里可以加上节流处理,减少性能消耗
        //document.addEventListener('scroll', throttle(lazyload(), 300))
        document.addEventListener('scroll', imgLazyLoad())
    </script>
</body>

</html>

上面代码提到的防抖处理可以看这个文章是如何实现的函数的节流

其它实现方式

上面代码已经写了非常详细的注释,相信已经非常的明了了。除了上面的方法,还可以通过以下两种方式来实现判断img已经出现在可视区内

  • offsetTop

通过offsetTop<clientHheight+scrollTop来判断img是否出现在可视区内

  • IntersectionObserver

这个属性可以自动检测元素是否可见