懒加载和预加载【转载】

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

一、懒加载

1、介绍

  • 懒加载也就是延迟加载。
  • 当访问一个页面的时候,先把所有img标签的src设为同一张空白图片的路径(占位图,只需请求一次),将其真正的图片地址存储在img标签的自定义属性中(比如data-src)
  • 两种加载情况:
    • 条件加载:符合某些条件,或触发了某些事件,才将自定义属性中的地址存储到src属性中,开始异步加载
    • 可视区加载:仅加载用户可以看到的区域。当js监听到该图片元素进入可视窗口时,将自定义属性中的地址存储到src属性中,开始异步加载。
#1、既然懒加载的原理是基于判断元素是否出现在窗口可视范围内,首先我们写一个函数判断元素是否出现在可视范围内:
function isVisible($node){
    var winH = $(window).height(),
        scrollTop = $(window).scrollTop(),
        offSetTop = $(window).offSet().top;
    if (offSetTop < winH + scrollTop) {
        return true;
    } else {
        return false;
    }
}

#2、再添加上浏览器的事件监听函数,让浏览器每次滚动就检查元素是否出现在窗口可视范围内:
$(window).on("scroll", function{
    if (isVisible($node)){
        console.log(true);
    }
})

#3、我们已经很接近了,现在我们要做的是,让元素只在第一次被检查到时打印true,之后就不再打印了
var hasShowed = false;
$(window).on("sroll",function{
    if (hasShowed) {
        return;
    } else {
        if (isVisible($node)) {
            hasShowed = !hasShowed;
            console.log(true);
        }
    }
})

实现代码:

  1 <!DOCTYPE html>
  2 <html>
  3 <head>
  4     <script src="http://apps.bdimg.com/libs/jquery/1.9.1/jquery.js
  5 "></script>
  6     <title>demo lazyload</title>
  7     <meta charset="utf-8">
  8     <style type="text/css">
  9         * {
 10             padding: 0;
 11             margin: 0;
 12             text-decoration: none;
 13             list-style: none;
 14         }
 15         .layout {
 16             margin: 0 auto;
 17              1000px;
 18         }
 19         .lazyload img {
 20              300px;
 21             height: 400px;
 22         }
 23         .img-ct {
 24             margin-left: -50px;
 25             overflow: auto;
 26         }
 27         .item {
 28             float: left;
 29             margin-left: 50px;
 30             margin-bottom: 30px;
 31         }
 32     </style>
 33 </head>
 34 <body>
 35 <div class="lazyload">
 36   <div class="layout">
 37     <ul class="img-ct">
 38         <li class="item">
 39             <a href="javascript:void(0)"><img data-img="img/Tsingtao.jpeg" src="img/blank.jpg"></a>
 40         </li>
 41         <li class="item">
 42             <a href="javascript:void(0)"><img data-img="img/Tsingtao.jpeg" src="img/blank.jpg"></a>
 43         </li>
 44         <li class="item">
 45             <a href="javascript:void(0)"><img data-img="img/Tsingtao.jpeg" src="img/blank.jpg"></a>
 46         </li>
 47         <li class="item">
 48             <a href="javascript:void(0)"><img data-img="img/Tsingtao.jpeg" src="img/blank.jpg"></a>
 49         </li>
 50         <li class="item">
 51             <a href="javascript:void(0)"><img data-img="img/Tsingtao.jpeg" src="img/blank.jpg"></a>
 52         </li>
 53         <li class="item">
 54             <a href="javascript:void(0)"><img data-img="img/Tsingtao.jpeg" src="img/blank.jpg"></a>
 55         </li>
 56         <li class="item">
 57             <a href="javascript:void(0)"><img data-img="img/Tsingtao.jpeg" src="img/blank.jpg"></a>
 58         </li>
 59         <li class="item">
 60             <a href="javascript:void(0)"><img data-img="img/Tsingtao.jpeg" src="img/blank.jpg"></a>
 61         </li>
 62         <li class="item">
 63             <a href="javascript:void(0)"><img data-img="img/Tsingtao.jpeg" src="img/blank.jpg"></a>
 64         </li>
 65         <li class="item">
 66             <a href="javascript:void(0)"><img data-img="img/Tsingtao.jpeg" src="img/blank.jpg"></a>
 67         </li>
 68         <li class="item">
 69             <a href="javascript:void(0)"><img data-img="img/Tsingtao.jpeg" src="img/blank.jpg"></a>
 70         </li>
 71         <li class="item">
 72             <a href="javascript:void(0)"><img data-img="img/Tsingtao.jpeg" src="img/blank.jpg"></a>
 73         </li>
 74         <li class="item">
 75             <a href="javascript:void(0)"><img data-img="img/Tsingtao.jpeg" src="img/blank.jpg"></a>
 76         </li>
 77         <li class="item">
 78             <a href="javascript:void(0)"><img data-img="img/Tsingtao.jpeg" src="img/blank.jpg"></a>
 79         </li>
 80     </ul>
 81   </div>
 82 </div>
 83 
 84 
 85 <script type="text/javascript">
 86 var lazyLoad = (function(){
 87     var clock;
 88     
 89     function init(){
 90         $(window).on("scroll", function(){
 91             if (clock) {
 92                 clearTimeout(clock);
 93             }
 94             clock = setTimeout(function(){
 95                 checkShow();
 96             }, 200);
 97         })
 98         checkShow();
 99     }
100     
101     function checkShow(){
102         $(".lazyload img").each(function(){
103             var $cur =$(this);
104             if($cur.attr('isLoaded')){
105                 return;
106               }
107             if(shouldShow($cur)){
108                 showImg($cur);
109             }
110         })
111     }
112     function shouldShow($node){
113         var scrollH = $(window).scrollTop(),
114             winH = $(window).height(),
115             top = $node.offset().top;
116         if(top < winH + scrollH){
117               return true;
118           }else{
119               return false;
120           }
121     }
122     function showImg($node){
123         $node.attr('src', $node.attr('data-img'));
124         $node.attr('isLoaded', true);
125     }
126     return {
127         init: init
128     }
129 })()
130 lazyLoad.init();
131 </script>
132 </body>
133 </html>
View Code

3、目的

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

4、 懒加载要点

1.图片进入可视区域之后请求图片资源;

2.对于电商等图片较多,页面很长的业务场景很适用;

3.可以减少无效资源的加载;

4.并发加载的资源过多会阻塞js的加载,影响网站的正常使用;

二、预加载

1、介绍

    • 提前加载图片,当用户需要查看时可直接从本地缓存中渲染

2、目的

    • 图片预先加载到浏览器中,访问者便可顺利地在你的网站上冲浪,并享受到极快的加载速度。
    • 这对图片画廊及图片占据很大比例的网站来说十分有利,它保证了图片快速、无缝地发布,也可帮助用户在浏览你网站内容时获得更好的用户体验。

预加载要点:

1.图片等静态资源在使用之前的提前请求;

2.资源后续使用时可以从缓存中加载,提升用户体验;

3.页面展示的依赖关系维护(必需的资源加载完才可以展示页面,防止白屏等);

3、实现

实现预加载主要有三个方法:

1.html中img标签最初设置为display:none;

2.js脚本中使用image对象动态创建好图片;

3.使用XMLHttpRequest对象可以更加精细的控制预加载过程,缺点是无法跨域:

方法一 :

1             function loadImage(url, callback) {     
2                 var img = new Image(); //创建一个Image对象,实现图片的预下载     
3                 img.onload = function () { //图片下载完毕时调用callback函数。         
4                    callback(img);     
5                  };  
6                 img.src = url;     
7 };
  • 注意:要将img.src放在img.onload后面
    • 否则,若将img.src放在img.onload前面
      • 若没有缓存:没问题
        • 给img.src赋值后开始异步加载图片,加载过程的时间很长,当加载完图片时,onload的赋值语句已经执行,所以加载完图片发生onload事件时就会调用callback函数。
      • 若有缓存,有问题
        • 给img.src赋值后开始异步加载图片,加载过程的时间很短,当加载完图片时,还没有执行到onload的赋值语句,所以加载完图片发生onload事件时不会调用callback函数。
  • 问题:
    • 内存泄漏:img.onload引用的匿名函数形成了闭包,闭包的作用域链中保存着img,创建了循环引用
    • 只考虑了静态图片的加载,忽略了gif等动态图片,可能会多次触发onload

方法二 √:解决方法一的问题

1         function loadImage(url, callback) {     
2                 var img = new Image(); //创建一个Image对象,实现图片的预下载         
3                 img.onload = function () { //图片下载完毕时将img.onload设为null,并异步调用callback函数。         
4                     img.onload = null;    
5                     callback(img);     
6                 };  
7                 img.src = url;     
8 };
原文地址:https://www.cnblogs.com/dadonggg/p/8425274.html