对于图片较多的页面,使用懒加载可以大幅提高页面加载速度,提高用户体验。
懒加载的意义(为什么要使用懒加载) 对页面加载速度影响最大的就是图片,一张普通的图片可以达到几M的大小,而代码也许就只有几十KB。当页面图片很多时,页面的加载速度缓慢,几S钟内页面没有加载完成,也许会失去很多的用户。
所以,对于图片过多的页面,为了加速页面加载速度,所以很多时候我们需要将页面内未出现在可视区域内的图片先不做加载, 等到滚动到可视区域后再去加载。这样子对于页面加载性能上会有很大的提升,也提高了用户体验。
原理 将页面中的img标签src指向一张小图片或者src为空,然后定义data-src
(这个属性可以自定义命名,我才用data-src)属性指向真实的图片。src
指向一张默认的图片,否则当src
为空时也会向服务器发送一次请求。可以指向loading
的地址。
注:图片要指定宽高
1 <img src ="default.jpg" data-src ="http://ww4.sinaimg.cn/large/006y8mN6gw1fa5obmqrmvj305k05k3yh.jpg" />
当载入页面时,先把可视区域内的img标签的data-src
属性值负给src
,然后监听滚动事件,把用户即将看到的图片加载。这样便实现了懒加载。
代码 在写代码前,需要了解各种高度。先看这篇文章scrollTop,offsetTop,scrollLeft,offsetLeft
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 <head > <meta charset ="UTF-8" > <title > Document</title > <style > img { display : block; margin-bottom : 50px ; width : 400px ; height : 400px ; } </style > </head > <body > <img src ="default.jpg" data-src ="http://ww4.sinaimg.cn/large/006y8mN6gw1fa5obmqrmvj305k05k3yh.jpg" alt ="" > <img src ="default.jpg" data-src ="http://ww4.sinaimg.cn/large/006y8mN6gw1fa5obmqrmvj305k05k3yh.jpg" alt ="" > <img src ="default.jpg" data-src ="http://ww1.sinaimg.cn/large/006y8mN6gw1fa7kaed2hpj30sg0l9q54.jpg" alt ="" > <img src ="default.jpg" data-src ="http://ww1.sinaimg.cn/large/006y8mN6gw1fa7kaed2hpj30sg0l9q54.jpg" alt ="" > <img src ="default.jpg" data-src ="http://ww4.sinaimg.cn/large/006y8mN6gw1fa5obmqrmvj305k05k3yh.jpg" alt ="" > <img src ="default.jpg" data-src ="http://ww4.sinaimg.cn/large/006y8mN6gw1fa5obmqrmvj305k05k3yh.jpg" alt ="" > <img src ="default.jpg" data-src ="http://ww4.sinaimg.cn/large/006y8mN6gw1fa5obmqrmvj305k05k3yh.jpg" alt ="" > <img src ="default.jpg" data-src ="http://ww4.sinaimg.cn/large/006y8mN6gw1fa5obmqrmvj305k05k3yh.jpg" alt ="" > <img src ="default.jpg" data-src ="http://ww1.sinaimg.cn/large/006y8mN6gw1fa7kaed2hpj30sg0l9q54.jpg" alt ="" > <img src ="default.jpg" data-src ="http://ww4.sinaimg.cn/large/006y8mN6gw1fa5obmqrmvj305k05k3yh.jpg" alt ="" > <img src ="default.jpg" data-src ="http://ww4.sinaimg.cn/large/006y8mN6gw1fa5obmqrmvj305k05k3yh.jpg" alt ="" > </body >
JavaScript 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 <script> var num = document .getElementsByTagName ('img' ).length ; var img = document .getElementsByTagName ("img" ); var n = 0 ; lazyload (); window .onscroll = lazyload; function lazyload ( ) { var seeHeight = document .documentElement .clientHeight ; var scrollTop = document .documentElement .scrollTop || document .body .scrollTop ; for (var i = n; i < num; i++) { if (img[i].offsetTop < seeHeight + scrollTop) { if (img[i].getAttribute ("src" ) == "default.jpg" ) { img[i].src = img[i].getAttribute ("data-src" ); } n = i + 1 ; } } } </script>
jQuery 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 <script> var n = 0 , imgNum = $("img" ).length , img = $('img' ); lazyload (); $(window ).scroll (lazyload); function lazyload (event ) { for (var i = n; i < imgNum; i++) { if (img.eq (i).offset ().top < parseInt ($(window ).height ()) + parseInt ($(window ).scrollTop ())) { if (img.eq (i).attr ("src" ) == "default.jpg" ) { var src = img.eq (i).attr ("data-src" ); img.eq (i).attr ("src" , src); n = i + 1 ; } } } } </script>
使用节流函数进行性能优化 如果直接将函数绑定在scroll
事件上,当页面滚动时,函数会被高频触发,这非常影响浏览器的性能。
我想实现限制触发频率,来优化性能。
节流函数:只允许一个函数在N秒内执行一次。下面是一个简单的节流函数:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 function throttle (fun, delay, time ) { let timeout let startTime = new Date () return function ( ) { let context = this let args = Array .prototype .slice .call (arguments ) let curTime = new Date () clearTimeout (timeout) if (curTime - startTime >= time) { fun.apply (context, args) startTime = curTime } else { timeout = setTimeout (function ( ) { fun.apply (context, args) }, delay) } } }; function lazyload (event ) {}window .addEventListener ('scroll' ,throttle (lazyload,500 ,1000 ));
使用去抖函数进行性能优化 去抖相比较节流函数要稍微简单一点,去抖是让函数延迟执行,而节流比去抖多了一个在一定时间内必须要执行一次。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 function debounce (fn, delay ) { let timer = null return function ( ) { let context = this let args = Array .prototype .slice .call (arguments ) clearTimeout (timer) timer = setTimeout (function ( ) { fn.apply (context, args) }, delay) } } function lazyload (event ) {}window .addEventListener ('scroll' ,throttle (lazyload,500 ));