前言
侦听事件和回调函数都可以实现对函数的执行,我们用图片预加载来分析 addEventListener 和 callback 的区别。
需求:页面中需要加载大量图片,当图片按顺序加载完后执行对应的操作。
分析:
- 大量图片,肯定会涉及到数组遍历,但遍历是同步的,load加载事件是异步的,需要考虑每次遍历的时候加载一张图片
- 避免出现回调地狱,尽可能少创建图片对象
- 每张图片的大小不一样,加载时间也不相同,要注意加载图片的顺序
- 函数执行完后最后需要对变量进行销毁
函数代码:
function loadImage(arr,callback){
//创建一个img对象
var img=new Image();
//给img侦听加载事件
img.addEventListener("load",loadHandler);
//给图片设置src,触发load
img.src=arr[0];
//参数传递
img.arr=arr;
img.resultArr=[];
img.num=0;
img.callback=callback;
}
//图片加载的时候执行该函数
function loadHandler(e){
//将当前的img复制一个添加到resultArr中
this.resultArr.push(this.cloneNode(false));
//num++,下一个图片的路径
this.num++;
//如果num大于当arr的长度,则表示遍历完毕
if(this.num>this.arr.length-1){
//如果有传callback参数,则直接调用
if(this.callback!==undefined){
this.callback(this.resultArr.slice());
//如果没有callback参数,给document抛发load_image_Finish事件,将resultArr传递出去
}else{
var evt=new Event("load_image_Finish");
evt.resultArr=this.resultArr.slice();
document.dispatchEvent(evt);
}
//对侦听和变量进行销毁
this.removeEventListener("load",loadHandler);
this.resultArr=null;
this.num=null;
this.callback=null;
return;
}
//将当前img的src设置成下一个
this.src=this.arr[this.num];
}
回调函数的调用方式:
//调用loadImage,传入callback
loadImage(arr,finishLoad);
//执行callback
function finishLoad(arr){
arr.forEach(function(item){
console.log(item.src);
})
}
事件侦听的执行方式:
//调用loadImage,没有传入callback
loadImage(arr);
//给document侦听load_image_Finish事件
document.addEventListener("load_image_Finish",finishLoad);
//执行finishLoad
function finishLoad(e){
e.resultArr.forEach(function(item){
console.log(item.src)
})
}
addEventListener 和 callback 的区别:
代码的概念上来讲,回调函数写起来容易 ,执行起来方便。 但是回调函数有依赖性,耦合度高,如果没有回调函数,会报错。
- 回调优点:写起来简单,执行方便。
- 缺点:耦合度高,有依赖性,没有回调函数的话,会报错。只能是一对一出现。
事件写法复杂,事件抛发只管抛,不需要知道是谁侦听,只要侦听的事件类型和侦听的事件对象一致,就可以侦听到。事件有侦听就执行,没有侦听也不会报错。
- 事件优点:分离化,不需要依赖。抛一次,可以多个地方执行侦听。
- 缺点:不好找错误,报错的话,不好找是哪里执行的。
事件抛发跟侦听 ,早期浏览器不支持。目前的手机浏览器都是最新的,所以所有手机的混合开发都是支持的