likes
comments
collection
share

惰性加载:优化资源管理与提升用户体验的现代策略

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

前言

什么是懒加载?

懒加载(Lazy Loading),又称为延迟加载或按需加载,是一种编程模式优化策略,用于推迟对象的初始化、数据的加载或资源的获取,直到它们真正被需要时才进行。

懒加载的意义:

  1. 提升页面加载速度:通过只加载可视区域的内容或用户即将查看的内容,懒加载显著减少了首次页面加载所需的时间,使页面能够更快地呈现给用户,提高了用户体验。
  2. 降低服务器负担:由于不是一次性加载所有资源,而是分批按需加载,这减少了服务器同时处理的请求数量和数据传输量,有助于降低服务器压力和带宽消耗。
  3. 提升系统性能:特别是在数据量庞大的应用中,如长列表、大型图像库等,懒加载可以有效减少内存占用,防止因一次性加载过多数据导致的系统响应缓慢或崩溃
  4. 适应性更强:懒加载机制可以根据设备性能、网络状况动态调整加载策略,为不同条件下的用户提供最适合的加载体验。

正文

思考一下

如果有很多图片时,图片全部用src来存取图片路径,这个时候可能页面的加载就会比较慢,这个时候我们可以采用懒加载的思想,即先加载一个屏幕内的图片,当滑动滚动条的时候,再加载该屏幕内的图片,所以 我们把图片的地址放在data-src中,src中放一个空白的照片的地址,代码如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>懒加载</title>
    <style>
        body{
            background-color: #96e173;
        }
        img {
            display: block;
            margin-bottom: 50px;
            width: 400px;
            height: 400px;
        }
    </style>
</head>
<body>
    <!-- data-src为数据属性 -->
    <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_1567641293753_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/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_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_1567640518658_img_png">
    <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">
</body>
</html>

js部分

大概的思路:

  • window绑定一个滚动事件,当滚动时触发回调函数lazyload

回调函数lazyload:

  1. 通过document.documentElement.clientHeight获取可视区域的一屏的高度screenHeight
  2. 通过document.documentElement.scrollTop获取滚动条距离顶部的距离scrollTop,也就是滚动条滚动的距离,但是这里鉴于浏览器的兼容性应该写成document.documentElement.scrollTop || document.body.scrollTop
  3. 通过for循环遍历图片,通过imgList[i].offsetTop < screenHeight + scrollTop(图片距离顶部的距离<一屏的高度+滚动的高度)判断该图片否在可视区域内,如果在就将data-src赋值给src
  4. 用一个变量n来记录已经渲染的图片的数量,用来判断图片是否已经全部渲染完,全部渲染完就移除window的滚动事件监听。
<script>
        const imgList = document.getElementsByTagName('img');
        const num = imgList.length;
        let n = 0;

        window.addEventListener('scroll', throttleLazyload);

        function lazyload() {
            // 获取可视区域一屏的高度
            let screenHeight = document.documentElement.clientHeight;
            // console.log(screenHeight);
            // 获取滚动条滚动的距离 多浏览器适配
            let scrollTop = document.documentElement.scrollTop || document.body.scrollTop;
            console.log(scrollTop);
            for (let i = n; i < num; i++) {
                
                if(imgList[i].offsetTop < screenHeight + scrollTop) {
                    imgList[i].src = imgList[i].getAttribute('data-src');
                    // 记录已经加载过的图片的下标
                    n = i + 1;
                    if(n === num) {
                        console.log('所有图片加载完成');
                        window.removeEventListener('scroll', throttleLazyload)
                    }
                }
        }
    }
    </script>

优化

  • 上面的代码已经基本可以实现效果了,但是要注意,前端一定要注意性能的优化,性能优化有防抖和节流等方法,这里要用到的方法是节流,因为当滚动条上下来回滚动时,会一直渲染已经渲染过的图片,所有我们要通过节流来处理这个问题。

节流函数:

 // 节流函数
    function throttle(func, limit) { 
          //记录当前是否在节流状态 
          let inThrottle;  

          //返回一个函数用于作为节流包装后的函数
          return function() {  
            // 保存当前调用的上下文和参数
            const context = this;  
            const args = arguments; 
            
            // 如果不在节流状态
            if (!inThrottle) {  
             //调用原函数,并传递当前的上下文和参数
              func.apply(context, args);  
              //将状态设置为节流状态中,阻止下一次的立即执行
              inThrottle = true; 
              //使用定时器在limit时间后重置节流状态,允许下一次执行 
              setTimeout(() => inThrottle = false, limit);  
            }  
        }
     }  
  • 第一次页面的图片应该在未滚动之前就调用一次回调函数,使用一个事件DOMCententLoaded

DOMContentLoaded事件:

当浏览器完成页面的初始HTML文档的加载和解析时触发,此时DOM树构建完成,而无需等待样式表、图片和子框架等异步资源完成加载。

 // DOMContentLoaded html和css页面加载完成时触发,保证第一次页面的图片不用滚轮加载图片
        document.addEventListener('DOMContentLoaded', () => {
            console.log('DOMContentLoaded');
            lazyload();
        })

代码简化

可以不用写节流函数,而是通过引入lodash库,调用里面的_.throttle方法。

总代码:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>懒加载</title>
    <style>
        body{
            background-color: pink;
        }
        img {
            display: block;
            margin-bottom: 50px;
            width: 400px;
            height: 400px;
        }
    </style>
</head>
<body>
    <!-- data-src为数据属性 -->
    <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_1567641293753_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/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_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_1567640518658_img_png">
    <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">
    <script src="https://cdn.bootcdn.net/ajax/libs/lodash.js/4.17.21/lodash.min.js"></script>
    <script>
        const imgList = document.getElementsByTagName('img');
        const num = imgList.length;
        let n = 0;
        // 注册在scroll事件中的触发函数
        const throttleLazyload = _.throttle(lazyload, 200);

        window.addEventListener('scroll', throttleLazyload);

        // DOMContentLoaded html和css页面加载完成时触发,保证第一次页面的图片不用滚轮加载图片
        document.addEventListener('DOMContentLoaded', () => {
            console.log('DOMContentLoaded');
            lazyload();
        })

        function lazyload() {
            // 获取可视区域一屏的高度
            let screenHeight = document.documentElement.clientHeight;
            // console.log(screenHeight);
            // 获取滚动条滚动的距离 多浏览器适配
            let scrollTop = document.documentElement.scrollTop || document.body.scrollTop;
            console.log(scrollTop);
            for (let i = n; i < num; i++) {
                
                if(imgList[i].offsetTop < screenHeight + scrollTop) {
                    imgList[i].src = imgList[i].getAttribute('data-src');
                    // 记录已经加载过的图片的下标
                    n = i + 1;
                    if(n === num) {
                        console.log('所有图片加载完成');
                        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; 
    //           //使用定时器在limit时间后重置节流状态,允许下一次执行 
    //           setTimeout(() => inThrottle = false, limit);  
    //         }  
    //     }
    //  }  
    </script>
</body>
</html>

效果:

惰性加载:优化资源管理与提升用户体验的现代策略

当滚动条滑动到底部时,表示所有的图片已经加载完成,此时控制台也不会输出了。

结语

惰性加载:优化资源管理与提升用户体验的现代策略

转载自:https://juejin.cn/post/7379873506543255562
评论
请登录