图片懒加载

图片懒加载

场景

一个网页会包含很多的图片,例如淘宝京东这些购物网站,商品图片很多,如果在首页就全部加载的话,会影响渲染速度(比如出现白屏)和浪费带宽,为了解决以上问题,提高用户体验,就出现了懒加载方式来减轻服务器的压力,优先加载可视区域的内容,其他部分等进入了可视区域再加载,从而提高性能。

原理

一张图片就是一个img标签,浏览器是否发起请求图片是根据img的src属性,所以实现懒加载的关键就是,在图片没有进入可视区域时,先不给img的src赋值,这样浏览器就不会发送请求了,等到图片进入可视区域再给src赋值。

实现

  1. 加载loading图片进行占位
  2. 判断哪些图片要加载
  3. 将loading图片替换真图片
代码语言:javascript
复制
<body>
    <div class="img-list">
        <img src="./loading.gif" data-src="1.jpg" width="300" height="300">
        <img src="./loading.gif" data-src="2.jpg" width="300" height="300">
        <img src="./loading.gif" data-src="3.jpg" width="300" height="300">
        <img src="./loading.gif" data-src="4.jpg" width="300" height="300">
        <img src="./loading.gif" data-src="5.jpg" width="300" height="300">
        <img src="./loading.gif" data-src="6.jpg" width="300" height="300">
        <img src="./loading.gif" data-src="7.jpg" width="300" height="300">
    </div>
&lt;script&gt;
    // 节流
    function throttle(fn, interval, option) {
        var lastTime = 0
        var timer
        var option = option || {}
        var trailing = option.trailing || false
        return function () {
            var _this = this
            var _arguments = arguments
            var newTime = new Date().getTime()

            if (timer) {
                clearTimeout(timer)
            }

            var result
            return new Promise((resolve, reject) =&gt; {
                if (newTime - lastTime &gt; interval) {
                    result = fn.apply(_this, _arguments)
                    resolve(result)

                    lastTime = newTime
                } else if (trailing) {
                    timer = setTimeout(() =&gt; {
                        result = fn.apply(_this, _arguments)
                        resolve(result)
                    }, interval);
                }
            })
        }
    }

    // 懒加载
    function lazy() {
        // 获取页面滚动条卷去的高度
        let bodyScrollHeight = parseInt(document.body.scrollTop || document.documentElement.scrollTop)
        // 获取页面高度
        let windowHeight = window.innerHeight
        // 获取所有img标签
        var imgs = document.querySelectorAll(&#39;img&#39;)
        // 延迟加载图片
        setTimeout(() =&gt; {
            for (let i = 0; i &lt; imgs.length; i++) {
                // 获取每个img标签距离body的高度
                let imgScrollTop = imgs[i].offsetTop
                /* 
                    (1)如果img标签距离body的高度 小于 页面高度+被卷去的高度,则代表当前img标签在可视区域,加载图片
                    (2)由于如果从最底部加载的话,最开头的图片一定符合(1),因此要判断img标签距离body的高度有没有大于滚动的高度,
                        大于滚动高度了才加载图片
                 */
                if (imgScrollTop &gt;= bodyScrollHeight &amp;&amp; imgScrollTop &lt; windowHeight + bodyScrollHeight) {
                    // 遍历img的所有属性
                    for (let j = 0; j &lt; imgs[i].attributes.length; j++) {
                        // 如果有data-src属性,将它的值赋给src
                        if (imgs[i].attributes[j].name == &#39;data-src&#39;) {
                            imgs[i].src = imgs[i].attributes[j].value
                            // 赋值后data-src就没用了,移除掉它
                            imgs[i].removeAttribute(&#39;data-src&#39;)
                        }
                    }
                }
            }
        }, 300);
    }

    // 刚进首页不触发滚动事件,因此要先加载一次
    lazy()

    // 监听滚动事件
    // window.addEventListener(&#39;scroll&#39;, lazy)

    // 用节流函数优化性能
    window.addEventListener(&#39;scroll&#39;, throttle(lazy, 100, { trailing: true }))

&lt;/script&gt;

</body>