likes
comments
collection
share

图片懒加载(Lazy Load)及初步性能优化

作者站长头像
站长
· 阅读数 58

图片懒加载(Lazy Load)及初步性能优化

在现代Web开发中,图片懒加载(Lazy Load)是一种非常有效的性能优化技术。它能够显著减少初次加载时间,提高用户体验。本文将深入探讨图片懒加载的原理、实现步骤及其在前端性能优化中的重要性。

浏览器的工作原理

要理解图片懒加载的意义,我们首先需要了解浏览器是如何加载和渲染网页的。以下是浏览器的主要工作步骤:

  1. 解析HTML:浏览器下载HTML文件并解析,建立DOM树(Document Object Model)。
  2. 下载CSS:解析和下载CSS文件,构建CSSOM树(CSS Object Model)。
  3. 渲染树:结合DOM树和CSSOM树,构建渲染树。
  4. 布局和绘制:计算每个元素的位置和大小,然后将内容绘制到屏幕上。
  5. 执行JavaScript:JavaScript是单线程的,但浏览器是多线程的,它会启动新的线程来下载和执行外部资源(如图片、脚本等)。

当浏览器解析到<img>标签时,会立即启动新的下载线程来获取图片。过多的并发下载可能导致网络堵塞,影响页面加载速度。因此,有必要控制图片的加载时机,尤其是那些在初次渲染时并不在视窗内的图片。

性能优化策略

为了提高页面加载性能,前端开发人员通常采用以下策略:

  1. 优先加载首屏图片:确保初次加载时,用户可以立即看到主要内容。
  2. 滚动懒加载:当用户滚动页面时,才开始加载视窗内的新图片。
  3. 减少并发请求:限制同时进行的图片下载数量,以避免网络堵塞。

图片懒加载的实现步骤

手动控制图片加载

默认情况下,<img>标签的src属性一旦被设置,浏览器会立即下载该图片。为了实现懒加载,我们可以使用自定义属性(如data-src)来存储图片的URL,并在需要时手动设置src属性。

代码示例

HTML结构说明

  • <head>部分引入了CSS文件和Lodash库。
  • <body>部分包含了10张图片,这些图片的src属性没有被设置,而是使用data-src属性存储图片的URL。
  • 使用了一个脚本来实现图片的懒加载。

JavaScript代码功能

  1. 变量声明

    • imgs:存储所有的图片元素。
    • num:图片的总数。
    • n:已加载图片的计数。
  2. loadImage函数

    • 获取视窗高度(screenHeight)。
    • 获取滚动条位置(scrollTop)。
    • 遍历所有图片,检查每张图片是否进入视窗(通过比较offsetTopscreenHeight + scrollTop)。
    • 如果图片进入视窗,则将其data-src属性赋值给src属性,从而触发图片加载。
    • 更新已加载图片计数n,如果所有图片已加载完毕,则移除滚动事件监听器。
  3. throttleLayLoad

    • 使用Lodash的throttle函数对loadImage函数进行节流处理,使其在500毫秒内最多执行一次。
  4. 事件监听器

    • scroll事件添加两个监听器:一个是经过节流处理的throttleLayLoad,另一个是原始的loadImage
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <!-- 引入公共CSS文件 -->
    <link rel="stylesheet" href="./common.css">
    <!-- 引入Lodash库用于节流函数 -->
    <script src="https://cdn.bootcdn.net/ajax/libs/lodash.js/4.17.21/lodash.min.js"></script>
</head>

<body>
    <!-- 使用data-src属性存储图片URL以实现懒加载 -->
    <img 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>
        // 获取所有图片元素
        const imgs = document.getElementsByTagName('img');
        const num = imgs.length; // 图片总数
        let n = 0; // 已加载图片计数

        // 懒加载图片的函数
        function loadImage() {
            let screenHeight = document.documentElement.clientHeight; // 视窗高度
            let scrollTop = document.documentElement.scrollTop || document.body.scrollTop; // 滚动条位置

            for (let i = 0; i < num; i++) {
                // 检查图片是否进入视窗
                if (imgs[i].offsetTop < screenHeight + scrollTop) {
                    // 设置图片src属性,触发加载
                    imgs[i].src = imgs[i].getAttribute('data-src');
                    n = i + 1;
                    // 如果所有图片已加载完毕,移除滚动事件监听器
                    if (n === num) {
                        window.removeEventListener('scroll', throttleLayLoad);
                    }
                }
            }
        }

        // 使用Lodash的节流函数,限制loadImage函数的执行频率
        const throttleLayLoad = _.throttle(loadImage, 500);
        // 添加滚动事件监听器,触发懒加载
        window.addEventListener('scroll', throttleLayLoad);
        window.addEventListener('resize', throttleLayLoad); // 添加窗口大小改变事件监听器
        window.addEventListener('orientationchange', throttleLayLoad); // 添加屏幕方向改变事件监听器

        // 页面加载完成后执行loadImage函数,确保首屏图片立即加载
        document.addEventListener('DOMContentLoaded', loadImage);
    </script>
</body>

</html>

CSS样式说明

  • 全局清除默认的marginpadding

  • 设置body的背景色为灰色。

  • 设置img元素:

    • display: block:使图片成为块级元素,占据一整行。
    • margin-bottom: 50px:每张图片底部有50px的间距。
    • width: 400pxheight: 400px:统一设置图片的宽高为400px。
* {
    margin: 0;
    padding: 0;
}
body {
    background-color: gray;
}
img {
    display: block;
    margin-bottom: 50px;
    width: 400px;
    height: 400px;
}

性能优化的收益

通过实现图片懒加载,我们可以显著提高页面的加载速度,特别是在图片较多的情况下。减少不必要的图片下载,避免网络拥塞,使用户在滚动页面时能更流畅地浏览内容。

浏览器底层原理

  • 下载线程:浏览器会为每个资源(如图片、脚本、样式表)启动新的下载线程,并行下载加速页面加载。
  • 并发数限制:浏览器对同一域名的并发请求数有限制(一般为6个),过多的并发请求会导致队列堵塞。

核心技术点

  1. clientHeight:视窗高度。
  2. scrollTop:滚动条顶部距离文档顶部的距离。
  3. offsetTop:元素距离文档顶部的距离。
  4. dataset:用于访问自定义数据属性(如data-src)。
转载自:https://juejin.cn/post/7379780178292195382
评论
请登录