事件dom
除IE8及以下版本的浏览器,绝大部分的浏览器都是支持W3C事件DOM。
谈到事件,需要首先了解三个基本概念。
事件源,也就是触发事件的dom元素对象。
事件名,一个事件源允许绑定多个事件,定义事件名可以指定触发了哪个事件。
响应,事件触发后执行了哪些操作。
一.事件的委派(较少使用)
即非直接触发事件对象,来触发事件。举个简单案例,即点击了按钮a却触发了按钮b绑定的事件。
代码案例0_1
<input id="a" type="button" οnclick="javascript:document.getElementById('a').fireEvent('onclick')" />
<input id="b" type="button" οnclick="javascript:alert('触发事件b')" />
由于fireEvent只在ie8及其以下版本中支持,需要兼容w3c中规范写法dispatchEvent(),兼容代码参考:
var dispatchEventComp = function(element, sEvent){
if(element.fireEvent){
element.fireEvent("on" + sEvent);
} else if(element.dispatchEvent){
var evt = document.createEvent("MouseEvents");
evt.initMouseEvent(sEvent,true,true,window,0,0,0,0,0,false,false,false,false,0,null);
//evt相当于手动创建了一个事件对象,这里记住这种写法即可,不作深入了解
element.dispatchEvent(evt);
}
}
兼容后修改代码如下:
代码案例0_2
<input id="a" type="button" οnclick="javascript:dispatchEventComp(document.getElementById('b'), 'click')" />
<input id="b" type="button" οnclick="javascript:alert('触发事件b')" />
二.事件的绑定与移除(使用频率高)
事件的绑定有两种声明:
1.直接对dom元素各类事件属性进行函数定义,如下:
document.getElementById("a").onclick = function(e){
console.log(e);
}
document.getElementById("a").onblur = function(e){
console.log(e);
}
其中参数e为默认传入的事件对象的相关信息
这种声明的一个特点就是只能定义相同操作类型事件一次,重复定义将只执行最后一次定义的操作。
属于dom0级定义。
2.通过attachEvent或addEventListener来声明绑定。属于dom2级定义。
其中attachEvent只对ie10及以下版本有效,addEventListener为W3C规范标准。
element.attachEvent("on"+eventType, listener)
eventType可以是click、blur、keydown、keyup等等方法,listener为触发后的函数操作,可以是已声明函数或直接是匿名函数。但需要注意的是,如果为匿名函数,那在使用事件移除方法detachEvent时,将无法移除该事件。
代码案例0_3
document.getElementById('a').attachEvent("onclick",function(e){alert('attachEvent事件绑定')})
element.addEventListener(eventType, listener, useCapture)
有别于attachEvent是具有useCapture这个参数,默认为false,即不在捕获阶段触发,一般事件都只在冒泡阶段再触发,ie8及以下版本中并不是支持捕获阶段声明的事件。
代码案例0_4
document.getElementById('a').addEventListener("click", function(e){console.log(e)});
兼容的写法如下:
var addEventListenerComp = function(element, eventType, listener){
if(element.addEventListener){
element.addEventListener(eventType, listener)
} else if(element.attachEvent){
element.attachEvent("on"+eventType, listener)
}
}
3.通过detachEvent或removeEventListener来声明移除。属于dom2级定义。
element.detachEvent("on"+eventType, handleEvent)
detachEvent与attachEvent配对使用,也是在ie10及以下版本才能使用。
element.removeEventListener(eventType, handleEvent, useCapture)
removeEventListener与addEventListener配对使用。useCapture指定处于捕捉阶段或冒泡阶段的handleEvent,一般都只在冒泡阶段触发事件,因此最好都别设置为true,默认不设置即为false。
其中handleEvent不能是匿名函数,否则移除无效。
兼容写法如下:
var removeEventListenerComp = function(element, eventType, listener){
if(element.removeEventListener){
element.removeEventListener(eventType, listener);
} else if(element.detachEvent){
element.detachEvent("on"+eventType, listener);
}
}
另外补充说明,以上所声明的element不止限制于dom元素对象,对文档自身、window、XMLHttpRequest都是适用的,但使用频率较高集中在dom元素对象。
三.事件流
W3C对事件流定义的三个阶段,捕获(capture),目标(object),冒泡(bubbling)。
在对多层结构进行事件绑定时,如果不了解清楚这三个阶段,将弄不清楚如何对事件传播进行拦截。
捕获阶段:
当鼠标在c_div中触发了事件,浏览器解析引擎会先捕捉到body元素,再捕捉p_div,再到c_div(这个过程为捕获阶段)。
目标阶段:
当传递到鼠标指向的c_div层时,此时就会触发该层绑定的事件。
冒泡阶段:
当执行完c_div层后的绑定事件,浏览器解析引擎又再进行回退的过程,将会逐层触发各层在冒泡阶段中绑定的事件。
如果不想事件执行冒泡阶段的事件,可以在对事件定义时,加上阻止事件传播的操作。
阻止事件传播操作的兼容代码如下:
var stopPropagation = function(e){//阻止事件的传播
if(e && e.stopPropagation){
e.stopPropagation();
} else {
var e = window.event;
e.cancelBubble = true;
}
}
代码案例0_5
document.getElementById('a').addEventListener("click", function(e){stopPropagation (e);console.log(e)});