预加载基本概念:当页面打开图片提前加载,并且缓存在用户本地,需要用到时直接进行渲染;在浏览图片较多的网页(百度图库,淘宝京东等),可以有更好的用户体验;
一张图片的预加载
1 var img=new Image(); 2 img.addEventListener("load",loadHandler); 3 img.src="./img/1.jpg"; 4 document.body.appendChild(img); 5 console.log(img.width); 6 7 function loadHandler(e){ 8 console.log(img.width);//当前图片的原始宽度 9 }
上面代码中,图片还没加载完成打印图片的宽度时,图片宽度为0;只有等图片加载完成后并写入DOM树渲染后,才去触发load事件的回调函数,才能打印出图片的宽度;
加载多张图片时,要提前在本地进行缓存,下面要讲三种预加载多张图片的例子:
第一种:load预加载
加载100张图片,且图片名为1.jpg~100.jpg(下同);
1 var num=1; 2 var list=[]; 3 loadImage(); 4 function loadImage(){ 5 var img=new Image(); 6 img.addEventListener("load",loadHandler); 7 img.src="./img/"+num+".jpg"; 8 } 9 function loadHandler(e){ 10 list.push(this.cloneNode());//复制当前图片元素 11 num++; 12 if(num>100){console.log(list);return;} 13 this.src="./img/"+num+".jpg"; //修改地址继续后触发load事件 14 }
上面代码表示:
1、创建一张图片;
2、给这个图片增加事件侦听load;
3、加载完成后,将加载进来的图片复制一个新的,放在数组中;
4、修改num;如果num的值大于100停止执行,并且打印数组;
5、给这个图片的地址赋予一个新地址,因为改变图片的地址就会重新触发load,所以会继续进入loadHandler函数,不断加载,直到加载完成。
第二种:生成器函数实现预加载
1 function loadImage(src){ 2 return new Promise(function(resolve,reject){ 3 let img=new Image(); 4 img.onload=function(){ 5 resolve(img);//加载时执行resolve函数 6 } 7 img.onerror=function(){ 8 reject(src+'这个地址错误');//抛出异常时执行reject函数 9 } 10 img.src=src; 11 }) 12 } 13 function* fn(){ 14 for(let i=1;i<100;i++){ 15 yield loadImage("./img/"+i+".jpg"); 16 } 17 } 18 let s=fn(); 19 let value=s.next().value; 20 resume(); 21 function resume(){ 22 value.then(img=>{ 23 console.log(img);//打印加载的图片标签 24 value=s.next().value; 25 if(value)resume(); 26 }); 27 }
以上代码表示:
1、执行生成器函数并且一次执行loadImage 函数;
2、在Promise中创建图片;
3、判断图片是否可以加载,加载成功执行Promise的回调函数resolve;
4、执行一次resume函数,并在函数里面执行Promise在resolved状态下的函数
5、反复执行s.next().value,直到全部图片加载完成;
第三种:async/await预加载图片
1 function loadImage(src){ 2 let p=new Promise(function(resolve,reject){ 3 let img=new Image(); 4 img.onload=function(){//加载时执行resolve函数 5 resolve(img); 6 } 7 img.onerror=function(){ 8 reject(src); 9 } 10 img.src=src; 11 }) 12 return p; 13 } 14 async function fn(){ 15 let arr=[]; 16 for(let i=3;i<80;i++){ 17 await loadImage(`./img/${i}-.jpg`).then(img=>{ 18 arr.push(img); 19 }); 20 } 21 return arr; 22 } 23 fn().then(list=>{ 24 console.log(list);//打印图片数组 25 })
这种方法是ES6的方法用到了async和await将异步转换为阻塞式同步;
说明:
1、fn 这个函数使用async 表示这个函数是一个异步函数2、这个函数中就可以使用await ,await作用就是让异步变为同步等待,异步变成了阻塞式等待3、当异步全部完成时,再继续向后运行4、async函数中的await后面只能跟的时Promise对象5、async函数执行后返回的是一个Promise对象
以上就是三种预加载的方法,仅供参考;