懒加载和预加载

参考链接:

懒加载和预加载

懒加载的原理及实现

处理图片预加载时设置img的src属性和img的onload事件的位置前后顺序关系

关于图片的预加载,你所不知道的

 

  • 页面中的img元素,如果没有src属性,浏览器就不会发出请求去下载图片,只有通过javascript设置了图片路径,浏览器才会发送请求。
  • 加载图片的过程是异步的

   

一、懒加载

  1. 介绍
    • 懒加载也就是延迟加载。
    • 当访问一个页面的时候,先把所有img标签的src设为同一张空白图片的路径(占位图,只需请求一次),将其真正的图片地址存储在img标签的自定义属性中(比如data-src)
    • 两种加载情况:
      • 条件加载:符合某些条件,或触发了某些事件,才将自定义属性中的地址存储到src属性中,开始异步加载
      • 可视区加载:仅加载用户可以看到的区域。当js监听到该图片元素进入可视窗口时,将自定义属性中的地址存储到src属性中,开始异步加载。

         

                        var lazyLoad = (function(){
                            var clock;
                            
                            function init(){
                                //监听浏览器滚动事件,持续滚动后停留200ms才会触发checkShow()
                                $(window).on("scroll", function(){
                                    if (clock) {
                                        clearTimeout(clock);
                                    }
                                    clock = setTimeout(function(){
                                        checkShow();
                                    }, 200);
                                })
                                checkShow();
                            }
                            
                            function checkShow(){
                                $(".lazyload img").each(function(){
                                    var $cur =$(this);
                                    //若某图片已经显示,则return
                                    if($cur.attr('isLoaded')){
                                        return;
                                    }
                                    //若某图片应该显示却还未显示,则将其显示出来
                                    if(shouldShow($cur)){
                                        showImg($cur);
                                    }
                                })
                            }
                            //判断图片是否应该显示
                            function shouldShow($node){
                                var scrollH = $(window).scrollTop(), //窗口的垂直滚动条位置
                                    winH = $(window).height(), //窗口高度
                                    top = $node.offset().top;  //图片相对于整个文档的偏移top坐标
                                if(top < winH + scrollH){
                                    return true;
                                }else{
                                    return false;
                                }
                            }
                            //将图片显示出来
                            function showImg($node){
                                $node.attr('src', $node.attr('data-src'));
                                $node.attr('isLoaded', true);
                            }
                            return {
                                init: init
                            }
                        })()
                        lazyLoad.init();

         

         

         

  2. 目的
    • 很多页面,内容很丰富,页面很长,图片较多,而且比较大。
    • 懒加载能防止页面一次性向服务器响应大量请求导致服务器响应慢,页面卡顿或崩溃等问题。
    • 减少请求数或延迟请求数,使页面加载速度快,用户体验好

   

二、预加载

  1. 介绍
    • 提前加载图片,当用户需要查看时可直接从本地缓存中渲染
  2. 目的
    • 图片预先加载到浏览器中,访问者便可顺利地在你的网站上冲浪,并享受到极快的加载速度。
    • 这对图片画廊及图片占据很大比例的网站来说十分有利,它保证了图片快速、无缝地发布,也可帮助用户在浏览你网站内容时获得更好的用户体验。
  3. 实现
    • 方法一 ×

       

                  function loadImage(url, callback) {     
                      var img = new Image(); //创建一个Image对象,实现图片的预下载     
                      img.onload = function () { //图片下载完毕时调用callback函数。         
                         callback(img);     
                       };  
                      img.src = url;     
      };

       

      • 注意:要将img.src放在img.onload后面
        • 否则,若将img.src放在img.onload前面
          • 若没有缓存:没问题
            • img.src赋值后开始异步加载图片,加载过程的时间很长,当加载完图片时,onload的赋值语句已经执行,所以加载完图片发生onload事件时就会调用callback函数。
          • 若有缓存,有问题
            • img.src赋值后开始异步加载图片,加载过程的时间很短,当加载完图片时,还没有执行到onload的赋值语句,所以加载完图片发生onload事件时不会调用callback函数。
      • 问题:
        • 内存泄漏:img.onload引用的匿名函数形成了闭包,闭包的作用域链中保存着img,创建了循环引用
        • 只考虑了静态图片的加载,忽略了gif等动态图片,可能会多次触发onload
    • 方法二 √:解决方法一的问题

       

                  function loadImage(url, callback) {     
                      var img = new Image(); //创建一个Image对象,实现图片的预下载         
                      img.onload = function () { //图片下载完毕时将img.onload设为null,并异步调用callback函数。         
                          img.onload = null;    
                          callback(img);     
                      };  
                      img.src = url;     
      };
<think>我们使用中文回答用户的问题。用户要求实现懒加载预加载的JavaScript代码,并在最后提出3-5个相关问题,且以“§§相关问题§§”开头,不换行分散。 懒加载(Lazy Loading):延迟加载图片或其他资源,直到它们进入视口(viewport)或即将进入视口时再加载。这可以提升页面加载速度性能。 预加载(Preloading):提前加载后续可能需要的资源(如图片、脚本等),以便在用户需要时能够快速展示,提升用户体验。 下面分别给出懒加载预加载的简单实现示例: ### 懒加载实现(以图片为例) 通常,我们使用`data-src`属性存放真实的图片路径,当图片进入视口时,将`data-src`的值赋给`src`属性。 HTML结构示例: ```html <img class="lazy" data-src="path/to/real-image.jpg" src="placeholder.jpg" alt="example"> ``` JavaScript实现: ```javascript document.addEventListener("DOMContentLoaded", function() { var lazyImages = [].slice.call(document.querySelectorAll("img.lazy")); if ("IntersectionObserver" in window) { let lazyImageObserver = new IntersectionObserver(function(entries, observer) { entries.forEach(function(entry) { if (entry.isIntersecting) { let lazyImage = entry.target; lazyImage.src = lazyImage.dataset.src; lazyImage.classList.remove("lazy"); lazyImageObserver.unobserve(lazyImage); } }); }); lazyImages.forEach(function(lazyImage) { lazyImageObserver.observe(lazyImage); }); } else { // 不支持IntersectionObserver的回退方案 // 可以监听scroll事件,使用getBoundingClientRect判断是否在视口内 // 这里为了简洁省略回退代码,实际项目中需要考虑 } }); ``` ### 预加载实现 预加载可以通过多种方式实现,例如使用`<link rel="preload">`标签,或者用JavaScript创建Image对象。 使用JavaScript预加载图片: ```javascript function preloadImage(url) { const img = new Image(); img.src = url; } // 预加载多张图片 const imageUrls = [ 'image1.jpg', 'image2.jpg', // 更多图片 ]; imageUrls.forEach(url => preloadImage(url)); ``` 使用`<link>`标签(在HTML中): ```html <link rel="preload" href="important-image.png" as="image"> ``` 注意:预加载可能会增加初始网络请求的负担,因此应谨慎使用,只预加载关键资源。 ### 回答总结 以上分别介绍了懒加载预加载的概念及简单实现懒加载适用于长页面中的图片或其他资源,以减少初始加载时间;预加载则用于提前加载用户可能很快访问的资源,以提升后续页面的响应速度。 §§相关问题§§ 1. 懒加载预加载在性能优化中的优缺点分别是什么? 2. 除了图片,懒加载预加载还可以应用于哪些类型的资源? 3. 如何实现一个支持懒加载的滚动列表(包括动态加载的数据)? 4. 在实现懒加载时,如何处理浏览器兼容性问题(如不支持IntersectionObserver的情况)? 5. 预加载的资源在浏览器缓存中会保存多久?如何控制?</think>### JavaScript实现懒加载预加载 #### 懒加载实现(Lazy Loading) 懒加载核心思想:当资源进入可视区域时再加载 ```javascript // 图片懒加载实现 const lazyImages = document.querySelectorAll('img[data-src]'); const imgObserver = new IntersectionObserver((entries, observer) => { entries.forEach(entry => { if (entry.isIntersecting) { const img = entry.target; img.src = img.dataset.src; img.removeAttribute('data-src'); observer.unobserve(img); } }); }, { rootMargin: '0px 0px 200px 0px' }); // 提前200px加载 lazyImages.forEach(img => { imgObserver.observe(img); }); ``` #### 预加载实现(Preloading) 预加载核心思想:提前加载后续需要的资源 ```javascript // 图片预加载实现 function preloadImages(imageUrls) { imageUrls.forEach(url => { const img = new Image(); img.src = url; }); } // 使用示例 preloadImages([ 'hero-banner.jpg', 'featured-product.png', 'promo-video-poster.jpg' ]); // 使用<link>标签预加载(推荐方式) const preloadLink = document.createElement('link'); preloadLink.rel = 'preload'; preloadLink.as = 'image'; preloadLink.href = 'critical-image.jpg'; document.head.appendChild(preloadLink); ``` #### 核心区别对比 | **特性** | 懒加载 | 预加载 | |----------------|---------------------------|---------------------------| | **加载时机** | 进入可视区域时加载 | 提前加载关键资源 | | **适用场景** | 长页面/非首屏内容 | 关键路径资源/下一页内容 | | **性能影响** | 减少初始加载量 | 增加初始加载量但提升后续体验 | | **实现复杂度** | 需监听滚动/交叉观察 | 简单声明即可 | #### 最佳实践建议 1. **懒加载适用**:商品列表、评论区、图库等非首屏内容 2. **预加载适用**:首屏大图、字体文件、关键CSS/JS 3. **组合使用**:首屏关键资源预加载 + 非关键内容懒加载 4. **添加加载状态**:使用占位符或加载动画提升体验 5. **兼容处理**:对不支持IntersectionObserver的浏览器提供polyfill
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值