- 页面中的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>
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 };