图片懒加载

2022-02-25 19:43:29 浏览数 (2)

图片懒加载

场景

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

原理

一张图片就是一个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>

    <script>
        // 节流
        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) => {
                    if (newTime - lastTime > interval) {
                        result = fn.apply(_this, _arguments)
                        resolve(result)

                        lastTime = newTime
                    } else if (trailing) {
                        timer = setTimeout(() => {
                            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('img')
            // 延迟加载图片
            setTimeout(() => {
                for (let i = 0; i < imgs.length; i  ) {
                    // 获取每个img标签距离body的高度
                    let imgScrollTop = imgs[i].offsetTop
                    /* 
                        (1)如果img标签距离body的高度 小于 页面高度 被卷去的高度,则代表当前img标签在可视区域,加载图片
                        (2)由于如果从最底部加载的话,最开头的图片一定符合(1),因此要判断img标签距离body的高度有没有大于滚动的高度,
                            大于滚动高度了才加载图片
                     */
                    if (imgScrollTop >= bodyScrollHeight && imgScrollTop < windowHeight   bodyScrollHeight) {
                        // 遍历img的所有属性
                        for (let j = 0; j < imgs[i].attributes.length; j  ) {
                            // 如果有data-src属性,将它的值赋给src
                            if (imgs[i].attributes[j].name == 'data-src') {
                                imgs[i].src = imgs[i].attributes[j].value
                                // 赋值后data-src就没用了,移除掉它
                                imgs[i].removeAttribute('data-src')
                            }
                        }
                    }
                }
            }, 300);
        }

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

        // 监听滚动事件
        // window.addEventListener('scroll', lazy)

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

    </script>

</body>

0 人点赞