由于ie中绑定事件的bug,所以产生了用原生的实践操作来模拟事件绑定的方法,跟着李炎恢学的一招。
function addEvent(obj, type, fn){
if(obj.addEventListener){
obj.addEventListener(type, fn, false);
}else{
if(!obj.events) obj.events = {};
if(!obj.events[type]) {
obj.events[type] = [];
if(obj['on'+ type]) obj.events[type][0] = fn; //这一步的时候 其实我看到的视频和文档上李炎恢大神并没有说清楚为什么要加个判断,仅仅说了一句可以减少一次绑定,没说为什么。多看几遍之后发现,是因为如果不加判断,会在页面加载之后,还不需要出发事件呢,他就绑定了第一个函数。所以需要确认,只有在我们需要绑定函数的时候,才能将函数赋值到数组的第一位上。
}else{
if(addEvent.equal(obj.events[type], fn)) return false; //对所有已经绑定的同类型事件进行循环,如果当前需要绑定的事件,已经绑定过一次,则跳出事件绑定。
}
obj.events[type][addEvent.ID++] = fn; //非初次绑定事件的累加
obj['on' + type] = addEvent.exec; //执行所有已经绑定的事件
}
}
addEvent.ID = 1;
addEvent.equal = function(es, fn){ //遍历保存的事件,如果有与新增的绑定事件相同的事件,则新增的事件不予绑定
for(var i in es){
if(es[i] == fn) return true;
}
return false;
}
addEvent.exec = function(e){
var e = e || addEvent.fixEvent(window.event);
var es = this.events[e.type]; //这里有个小坑,由于上面主体函数参数名也有一个type,所以很容易误解为两个type是一样的,其实并不是。参数type仅仅是一个参数名称,没有具体的意义,可以改成任何参数名称,但是这里的type是事件对象e的一个属性,可以获取当前出发的究竟是什么事件类型。
for (var i in es){
es[i].call(this, e); //使用call,主要目的是为了传递参数this和e
}
}
addEvent.fixEvent = function(ev){
ev.preventDefault = function(){
this.returnValue = false;
}
ev.stopPropagation = function(){
this.cancelBubble = true;
}
ev.target = window.event.srcElement;
return ev;
}
巩固复习一遍。