JavaScript中的预加载和懒加载
预加载和懒加载的使用场景不同,可以先了解一下浏览器机制,有助于理解两者的原理。在网页中合理使用预加载和懒加载有效地减少用户的等待时间,提高用户体验。
目录
页面加载过程
预加载
懒加载
页面加载过程
简单说一下页面的加载过程,如果页面不是第一次访问,那么可能会出现浏览器缓存现象,在本地调试代码的时候也会遇到这种问题,所以在实在想不通页面为什么没有变化的时候,可以清除一下浏览器的缓存。
如果页面是第一次访问,浏览器向服务器http请求后,服务器返回html文件,在整个页面加载过程中,总的来说是按顺序从上到下执行,这是基于js的单线程机制,但是html和css是并行加载的,html生成dom树,css生成rule树,两者相结合生成render树。
接下来遇到js文件,则会造成堵塞,页面会一直等到js文件执行完才会进行下一步操作。
在进行html中body部分加载时,如果遇到图片的src,它会请求资源,此时图片还没下载完全,在页面上并不会留下图片的位置,而html不会堵塞,将会继续执行下去。
等到有图片请求下载完成,html又会重新渲染页面,将图片显示出来。
了解了页面的加载过程后更好理解预加载和懒加载,对页面进行更好的优化。
预加载
预加载的核心:
图片等静态资源在使用前提前请求。
资源后续使用可以直接从缓存中加载,提升用户体验。
几个误区:
预加载不是为了减少页面加载时间
预加载只是提前加载除去首轮加载的图片以后要用到的图片,比如通过点击等事件才会用到的图片。
预加载的三种方式
一、css+javascript
仅使用css的情况:
1 2 3 4 5 | #preload-01 { background: url(img1.png); }#preload-02 { background: url(img2.png); }#preload-03 { background: url(img3.png); } |
preload-01、preload-02、preload-03实际上是不会在页面上显示的,它们的作业就是为了预加载图片上面的图片。在执行了上面的css后,本地就已经有了上面的图片缓存,后面如果还需要该图片,则直接从缓存在读取,减少了用户的等待时间。
在前面提到,预加载不是为了减少页面加载时间,但是向上面那样写,预加载和页面上其他内容一起加载,还会加长页面的加载时间,用户在点进页面时,等待时间加长,并没有达到我们提高用户体验的目的,我们可以封装一个函数,推迟预加载时间,等页面加载完成后再预加载。
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 | function preload(){ if(document.getElementById){ document.getElementById("preload-01").style.background = "url(img1.png)"; document.getElementById("preload-02").style.background = "url(img2.png)"; document.getElementById("preload-03").style.background = "url(img3.png)"; }}function addLoadEvent(func){ var oldonload = window.onload; if(type window.onload != "function"){ window.onload = func; }else{ window.onload = function(){ if(oldonload){ oldonload(); } func(); } }}addLoadEvent(preload); |
或者可以直接将上面的preloader函数放在body的最后,在所有js的最后执行。
二、仅使用JavaScript
上面的方法将图片放在css里实现预加载,也可以仅使用JavaScript来实现预加载。在js中,需要多少预加载图片,就创建多少image对象,再为每个image对象添加图片的src,此时图片也会被提前请求。
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 | var images = new Array();function preload(){ for(var i = 0;i < preload.arguments.length;i ++){ iamges[i] = new Image(); images[i].src = preload.arguments[i]; }}preload(url1,url2,url3);//也可以将上面的代码改写一下function preload(){ if(document.images){//document.images:页面上所有图片的集合 var img1 = new Image(); var img2 = new Image(); var img3 = new Image(); img1.src = url1; img2.src = url2; img3.src = url3; }} |
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | window.onload = function(){ setTimeout = (function(){ var xhr = new XMLHttpRequest(); xhr.open('GET','js文件地址'); xhr.send(''); xhr = new XMLHttpRequest(); xhr.open('GET','css文件地址'); xhr.send(''); new Image().src = '图片地址'; },1000);}//另一种写法window.onload = function(){ setTimeout(function(){ var head = document.getElementsByTagName('head')[0]; var css = document.createElement('link'); css.type = 'text/css'; css.rel = 'stylesheet'; css.href = 'css地址'; var js = document.createElement('script'); js.type = 'text/javascript'; js.src = 'js地址'; head.appendChild(css); head.appendChild(js); new Image().src = '图片地址'; },1000)} |
这里使用setTimeout的原因是为了防止脚本被挂起,可以了解一下浏览器的GUI渲染线程和JS引擎,两者是相斥的,在JS引擎执行时,html文档会挂起渲染(加载解析渲染同步)的线程,不仅要等待文档中js文件加载完毕,还要等待解析执行完毕,才可以恢复html文档的渲染线程。
懒加载
懒加载的核心:
仅显示可视区的图片资源,不可见区域的资源暂不请求。
使用懒加载可以减少页面的加载时间。
使用于需要大量图片的页面。
实现要点:将图片的src设为空,或者也可以将所有图片的src设一个底图,当图片还没加载完时,用这张底图来占图片的位置,防止页面结构混乱。再给一个自定义的data-url属性,用来存放图片的真实路径。lazyload属性用来标明哪些图片是需要懒加载。监听滚动事件,只在图片出现在可视区时,才动态地将图片的真实地址赋予图片的src属性。
1 | <img src="" lazyload="true" data-url="1.jpg"/> |
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | var viewHeight = document.documentElement.clientHeight;//可视区域的高度function lazyload(){ var eles = document.querySelectorAll('img[data-url][lazyload]'); Array.prototype.forEach.call(eles,function(item,index){ var rect; if(item.dataset.url === ''){//html5 data 钩子的写法 return; } rect = item.getBoundingClientRect();//getBoundingClientRect()返回一个矩形对象. if(rect.bottom >= 0 && rect.top < viewHeight){ !function(){//感叹号表明这是一个函数表达式 var img = new Image(); img.src = item.dataset.url; img.onload = function(){ item.src = img.src; } item.removeAttribute('data-url'); item.removeAttribute('lazyload'); }() } })}lazyload();//首屏调用document.addEventListener('scroll',lazyload); |
文章转载至:https://blog.csdn.net/AHRL__/article/details/80207605