提高你前端页面加载性能的简单方法---图片懒加载

1,050 阅读5分钟

前言

在我学习前端性能优化过程中,了解到浏览器启动时会做的一些工作,由于浏览器是多线程运行,可以同时渲染很多张图片,那么问题来了,前端页面加载少量图片的时候很流畅,看不出卡顿,那么在大项目中一个页面渲染几百几千张图呢?是不是它们一下加载的话就会出现卡顿呢?这可会大大影响用户的体验啊。所有我们就学习一种图片加载性能的优化方式那就是----图片懒加载。

图片懒加载

它是一种常见的前端优化技术,主要用于改善网页性能和提升用户体验。在页面初始化时,只加载可视区域内的图片,当用户滚动页面,将要进入可视区域的图片才开始加载,这就是图片懒加载。

实现图片懒加载的方法有多种:

  1. 使用JavaScript或jQuery:通过监听滚动事件,判断图片是否进入可视区域,然后动态地为图片添加src属性。
  2. 使用Intersection Observer API:这是一种现代浏览器支持的API,可以更高效地检测元素是否进入视口,从而触发图片加载。
  3. *使用CSS和data-属性:在图片标签中使用data-src属性存储图片的真实路径,然后通过JavaScript在适当的时机替换为src属性。
  4. 使用第三方库:例如lozad.js、lazyload.js等,这些库提供了现成的解决方案,可以方便地实现图片懒加载。

图片懒加载的优点是减少初始页面加载时间,节省带宽,提高用户体验。缺点是需要额外的JavaScript代码,对于SEO可能有轻微影响(搜索引擎爬虫可能无法执行JavaScript,导致图片无法被正确识别)。

这里我们用第一个方法,使用JavaScript进行事件监听(主要是其它方法还不会哈哈哈)。

具体实现步骤

  • 首先我们准备十几张图片:

image.png

  • 给每一张图片的src设置为空,而data-src 是一个自定义数据属性,属于 HTML5 数据属性的一部分,其前缀 data- 表明这是一个用于存储私有自定义数据的属性。
  • 在图片懒加载的场景下,<img> 标签的 src 属性可能会被设置为一个占位符图片的 URL 或者留空,而实际的图片 URL 则存储在 data-src 属性中。

实现步骤主要需理解img标签的src属性如果存了图片的url地址,浏览器加载页面时图片就会立马下载,所有才用data-src属性先存入src属性。

然后在JavaScript内拿到基本数据:

image.png

  • 再设计一个事件监听,DOMContentLoaded 是一个在文档解析完成后的事件,但不包括样式表、图片和iframe的完成加载。这是JavaScript中的一个非常重要的事件,因为它标志着DOM树已经构建完成,此时可以通过JavaScript访问和操作DOM元素。

image.png

这个可以作为页面的第一次加载图片,后面可以触发其他事件来进行页面图片加载。

  • 这样我们就可在加载函数内进行图片的懒加载了实现了:我们现在来分析一下,当进入页面时,我们需要加载当前显示屏显示的图片以及浏览过的图片,下面未浏览的图片暂时不显示。

  • 也就是说,当前图片距离页面顶部的距离 应该小于 滑屏滚动的距离加上显示器的长度。 可加载的图片的条件判断如下:imgs[i].offsetTop < screenHeight + scrollTop

image.png

  • 循环每一张图片,如果满足判断条件,则将data-srcurl地址赋值给img标签的src属性。

image.png imgs[i] 获取到了数组中第i个 <img> 元素,.dataset.src 则获取了该元素的 data-src 属性的值。

设置这段代码的意思是 当所有的图片都加载完成后,这个函数将不再被调用,其监听事件将被移除。监听的scroll事件是鼠标滚轮事件,因为我们每次滚动滑轮都会触发函数,让其重新计。

n = i + 1;
if(n === num){
    console.log('所有图片均以加载完毕')
    window.removeEventListener('scroll',throttleLayLoad)
}

然后完成加载后,调用如下函数:

_.throttle 函数是来自 Lodash 库的一个实用工具函数,用于限制函数的执行频率,即确保函数在指定的时间间隔内最多只能执行一次。这对于处理高频率触发的事件,比如窗口的滚动事件、调整大小事件等,特别有用,可以防止函数过于频繁地执行,从而优化性能。

image.png

最终效果如下:

刚开始页面只加载3张图:

image.png

当我们的不断的往下划时,图片会继续的加载。

image.png

这里对比一下不加_.throttle 函数的执行次数:

_.throttle 函数:该函数会限制重载函数的执行,避免没必要的计算,以及无意义的函数执行。 image.png

image.png

没有_.throttle 函数:鼠标滑轮一动,它的函数就会执行多次。

image.png

image.png

最终的完整代码如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        *{
            margin: 0;
            padding: 0;
        }
body{
    background-color: gray;
}

img{
    display: block;
    margin-bottom: 50px;
    width: 400px;
    height: 400px;
}
    </style>
</head>
<body>
    <img  data-price="20" data-src="https://img.36krcdn.com/20190808/v2_1565254363234_img_jpg">
    <img  data-src="https://img.36krcdn.com/20190905/v2_1567641293753_img_png">
    <img   data-src="https://img.36krcdn.com/20190905/v2_1567640518658_img_png">
    <img   data-src="https://img.36krcdn.com/20190905/v2_1567642423719_img_000">
    <img   data-src="https://img.36krcdn.com/20190905/v2_1567642425030_img_000">
    <img  data-src="https://img.36krcdn.com/20190905/v2_1567642425101_img_000">
    <img data-src="https://img.36krcdn.com/20190905/v2_1567642425061_img_000">
    <img  data-src="https://img.36krcdn.com/20190904/v2_1567591358070_img_jpg">
    <img  data-src="https://img.36krcdn.com/20190905/v2_1567641974410_img_000">
    <img  data-src="https://img.36krcdn.com/20190905/v2_1567641974454_img_000">
    <script src="https://cdn.bootcdn.net/ajax/libs/lodash.js/4.17.21/lodash.min.js"></script>
    <script>
        const imgs = document.getElementsByTagName('img');
        const num = imgs.length;
        let n = 0;
        document.addEventListener('DOMContentLoaded',()=>{
            loadImage()
        })
        function loadImage(){
            console.log('haha')
            // 是否在可视区?
            let screenHeight = document.documentElement.clientHeight;// 一整个屏幕的高度 宽度
            let scrollTop = document.documentElement.scrollTop || document.body.scrollTop;  // 滚动条上的偏移量(滚动的距离) 不同浏览器兼容问题
            for(let i = 0; i < num; i++){
                // console.log(imgs[i].offsetTop);
                if(imgs[i].offsetTop < screenHeight + scrollTop){
                    // console.log(imgs[i].dataset.src);
                    imgs[i].src = imgs[i].dataset.src; //或者imgs[i].getAttribute('data-src')
                    n = i + 1;
                    if(n === num){
                        console.log('所有图片均以加载完毕')
                        window.removeEventListener('scroll',throttleLayLoad)
                    }
                }
            }
        }
        const throttleLayLoad = _.throttle(loadImage,500);
        window.addEventListener('scroll',throttleLayLoad);
    </script>
</body>
</html>

总结

图片懒加载技术显著优化了网页性能和用户体验,通过延迟非可视区域图片的加载,它有效加快了页面初次加载速度,节约了带宽和数据流量,同时也减轻了服务器负担。这一做法确保了用户能快速的看到页面主要内容,避免了渲染阻塞,优化了资源使用,特别是在长页面中避免加载未被浏览的图片。