javascript技巧

关注公众号 jb51net

关闭
首页 > 网络编程 > JavaScript > javascript技巧 > JavaScript优化图片懒加载

JavaScript优化图片懒加载的性能技巧

作者:睡着学

前端发展过程中有许多性能优化的操作,比如防抖、节流和图片懒加载等,在这里我们首先聊聊图片懒加载操作,我们会经常逛像淘宝和京东等购物平台,一次性全部加载会导致加载时间长、网络资源消耗大,所以本文给大家介绍了JavaScript优化图片懒加载的性能技巧

背景

前端发展过程中有许多性能优化的操作,比如防抖、节流和图片懒加载等。在这里我们首先聊聊图片懒加载操作。

在最近的618中,我们会经常逛像淘宝和京东等购物平台。那你觉得在淘宝页面中的图片资源是打开页面时就一次性全部加载完了呢,还是在你滚轮滚动到的区域才加载图片呢。

一次性全部加载会导致加载时间长、网络资源消耗大、内存占用率高和发出大量图片请求给服务器带来的巨大压力。

所以采用的是只加载当前可见区域的图片,随着用户的滚动,当其他图片进入可见区域时,再进行加载。这种方法就是图片的懒加载。这种方式可以有效地提高页面的响应速度,特别是在图片数量较多或网络条件较差的情况下,可以避免页面加载缓慢或卡顿的现象,提供更好的用户体验。

如下图所示,淘宝页面刚打开时并不是全部加载的。

大致思路

图片懒加载布局逻辑:

图片懒加载交互逻辑:

编辑代码

html部分

<img src="https://misc.360buyimg.com/mtd/pc/common/img/blank.png"
     data-src="https://img.36krcdn.com/hsossms/20240612/v2_8ec7812750194dbd831babce8806c626@000000_oswg5522709oswg1792oswg1024_img_png?x-oss-process=image/resize,m_mfit,w_600,h_400,limit_0/crop,w_600,h_400,g_center/format,webp" />
<img src="https://misc.360buyimg.com/mtd/pc/common/img/blank.png"
     data-src="https://img.36krcdn.com/20190808/v2_1565254363234_img_jpg">
<img src="https://misc.360buyimg.com/mtd/pc/common/img/blank.png"
     data-src="https://img.36krcdn.com/20190905/v2_1567641293753_img_png">
<img src="https://misc.360buyimg.com/mtd/pc/common/img/blank.png"
     data-src="https://img.36krcdn.com/20190905/v2_1567640518658_img_png">
<img src="https://misc.360buyimg.com/mtd/pc/common/img/blank.png"
     data-src="https://img.36krcdn.com/20190905/v2_1567642423719_img_000">
<img src="https://misc.360buyimg.com/mtd/pc/common/img/blank.png"
     data-src="https://img.36krcdn.com/20190905/v2_1567642425030_img_000">
<img src="https://misc.360buyimg.com/mtd/pc/common/img/blank.png"
     data-src="https://img.36krcdn.com/20190905/v2_1567642425101_img_000">
<img src="https://misc.360buyimg.com/mtd/pc/common/img/blank.png"
     data-src="https://img.36krcdn.com/20190905/v2_1567642425061_img_000">
<img src="https://misc.360buyimg.com/mtd/pc/common/img/blank.png"
     data-src="https://img.36krcdn.com/20190904/v2_1567591358070_img_jpg">
<img src="https://misc.360buyimg.com/mtd/pc/common/img/blank.png"
     data-src="https://img.36krcdn.com/20190905/v2_1567641974410_img_000">
<img src="https://misc.360buyimg.com/mtd/pc/common/img/blank.png"
     data-src="https://img.36krcdn.com/20190905/v2_1567641974454_img_000">

在html部分中有一个重要的步骤。你会发现每一个img标签的src属性值都是一样的,我们可以复制链接到浏览器查看该图片。

该图片是中间的小白点:

该图片的属性如下:

可以看出这个图片是非常小的。在页面打开时,加载的都是这个图片,真正要加载的图片url放置在data-src数据属性里面。最后通过JavaScript部分实现将data-src数据属性的内容赋值给img标签的src属性,然后发送HTTP请求加载真正的图片。

css部分

img {
    display: block;
    margin-bottom: 50px;
    width: 400px;
    height: 400px;
}

body {
    background-color: gray;
}

通过设置img 标签样式,让小图片给真正要放的图片占位置。

JavaScript部分

const imgs = document.getElementsByTagName('img');
const num = imgs.length;
let n = 0
window.addEventListener('scroll', lazyload)
function lazyload() {
    //可视区域的高度
    let screenHeight = document.documentElement.clientHeight;
    //滚动条距离最顶部的距离,
    let scrollTop = document.documentElement.scrollTop || document.body.scrollTop;
    //判断图片是否存在在可视区域内
    for (let i = n; i < num; i++) {
        if (imgs[i].offsetTop > scrollTop + screenHeight) {
            break;
        } else {
            //主动触发下载
            imgs[i].src = imgs[i].getAttribute('data-src');
            //记录已经加载过的图片数量
            n = i + 1;
            if (n === num) {
                //全部加载完毕后移除滚动事件
                window.removeEventListener('scroll', lazyload);
            }
        }
    }
}
//方法一
document.addEventListener('DOMContentLoaded', lazyload)
//方法二
window.addEventListener('load', lazyload)

节流优化

因为scroll事件监听器在频繁的滑轮滚动会频繁触发。如果直接在事件处理函数中执行大量复杂的操作,可能会导致性能问题。

所以通过使用节流限制事件触发的频率。

const imgs = document.getElementsByTagName('img');
const num = imgs.length;
//用变量记录节流返回的函数
const throttleLazyLoad = throttle(lazyload, 200);
//滚动事件触发懒加载
window.addEventListener('scroll', throttleLazyLoad)
let n = 0
//首屏加载,DOMContentLoaded事件是DOM加载完成,不包括图片(比load事件快)
document.addEventListener('DOMContentLoaded', lazyload)
//首屏加载,load事件是DOM加载完成,包括图片(比DOMContentLoaded事件慢)
window.addEventListener('load', lazyload)
//懒加载函数
function lazyload(event) {
    //可视区域的高度
    let screenHeight = document.documentElement.clientHeight;
    //滚动条距离最顶部的距离,
    let scrollTop = document.documentElement.scrollTop || document.body.scrollTop;
    //判断图片是否存在在可视区域内
    for (let i = n; i < num; i++) {
        if (imgs[i].offsetTop > scrollTop + screenHeight) {
            break;
        } else {
            //主动触发下载
            imgs[i].src = imgs[i].getAttribute('data-src');
            //记录已经加载过的图片数量
            n = i + 1;
            if (n === num) {
                //全部加载完毕后移除滚动事件
                window.removeEventListener('scroll', throttleLazyLoad);
            }
        }
    }
}
//节流函数
function throttle(func, limit) {
    let inThrottle;
    return function () {
        const context = this;
        const args = arguments;
        if (!inThrottle) {
            func.apply(context, args);
            inThrottle = true;
            setTimeout(() => inThrottle = false, limit);
        }
    };
}

定义了一个节流函数,它接收要执行的函数 func 和时间间隔限制 limit。内部通过一个变量 inThrottle 来标记当前是否处于节流状态。当执行返回的函数时,先判断如果不在节流状态,就立即执行目标函数,并将 inThrottle 设置为 true,同时使用 setTimeout 在指定时间间隔后将 inThrottle 恢复为 false,从而实现了在规定时间间隔内只执行一次函数的节流效果,避免了频繁触发导致的性能问题。

再次优化

在日常工作时,如果让你选择手搓一个节流函数和直接使用工具库里的函数,你肯定也会和我一样偷懒,选择直接使用工具库里的现成的函数。

首先在HTML中使用以下代码引入 Lodash 库。

<script src="https://cdn.bootcdn.net/ajax/libs/lodash.js/4.17.21/lodash.min.js"></script>

然后可以删除掉你手搓的节流函数了,使用 Lodash 库里的节流函数。

const imgs = document.getElementsByTagName('img');
const num = imgs.length;
//用变量记录节流返回的函数
const throttleLazyLoad = _.throttle(lazyload, 200);//调用Lodash库里的节流函数
//滚动事件触发懒加载
window.addEventListener('scroll', throttleLazyLoad)
let n = 0
//首屏加载,DOMContentLoaded事件是DOM加载完成,不包括图片(比load事件快)
document.addEventListener('DOMContentLoaded', lazyload)
//首屏加载,load事件是DOM加载完成,包括图片(比DOMContentLoaded事件慢)
window.addEventListener('load', lazyload)
//懒加载函数
function lazyload(event) {
    //可视区域的高度
    let screenHeight = document.documentElement.clientHeight;
    //滚动条距离最顶部的距离,
    let scrollTop = document.documentElement.scrollTop || document.body.scrollTop;
    //判断图片是否存在在可视区域内
    for (let i = n; i < num; i++) {
        if (imgs[i].offsetTop > scrollTop + screenHeight) {
            break;
        } else {
            //主动触发下载
            imgs[i].src = imgs[i].getAttribute('data-src');
            //记录已经加载过的图片数量
            n = i + 1;
            if (n === num) {
                //全部加载完毕后移除滚动事件
                window.removeEventListener('scroll', throttleLazyLoad);
            }
        }
    }
}

呈现效果

当所有图片加载完后滚动事件就不会触发慢加载函数了,并且也有节流效果。

首屏的图片立即加载,区域图片在滚动到再加载。

以上就是JavaScript优化图片懒加载的性能技巧的详细内容,更多关于JavaScript优化图片懒加载的资料请关注脚本之家其它相关文章!

您可能感兴趣的文章:
阅读全文