原始事件模型
在原始事件模型中(也有说DOM0级),事件发生后没有传播的概念,没有事件流。事件发生,马上处理,完事,就这么简单。监听函数只是元素的一个属性值,通过指定元素的属性值来绑定监听器。书写方式有两种:
- HTML代码中指定属性值:
<input type=”button” onclick=”func1()” />
- 在js代码中指定属性值:
document.getElementsByTagName(‘input’)[0].onclick = func1
优点:所有浏览器都兼容
缺点:
- 逻辑与显示没有分离;
- 相同事件的监听函数只能绑定一个,后绑定的会覆盖掉前面的,如:a.onclick = func1; a.onclick = func2;将只会执行func2中的内容。
- 无法通过事件的冒泡、委托等机制(后面系列会讲到)完成更多事情。
DOM2事件模型
此模型是W3C制定的标准模型,既然是标准,那大家都得按这个来,我们现在使用的现代浏览器(指IE6~8除外的浏览器)都已经遵循这个规范。W3C制定的事件模型中,一次事件的发生包含三个过程:
(1)capturing phase:事件捕获阶段。事件被从document一直向下传播到目标元素,在这过程中依次检查经过的节点是否注册了该事件的监听函数,若有则执行。
(2)target phase:事件处理阶段。事件到达目标元素,执行目标元素的事件处理函数.
(3)bubbling phase:事件冒泡阶段。事件从目标元素上升一直到达document,同样依次检查经过的节点是否注册了该事件的监听函数,有则执行。
所有的事件类型都会经历captruing phase但是只有部分事件会经历bubbling phase阶段,例如submit事件就不会被冒泡。
<div id = 'outer' style = 'margin: 100px 0 0 100px; width: 200px;height: 200px; background: red;'>
<div id="inner" style = 'margin-left:20px; width: 50px;height:50px; background: green;'></div>
</div>
假设我们点击了ID为inner的div,那么此时的事件流程就是,首先执行捕获阶段:document-html-body-div(outer)。然后执行冒泡阶段:div(inner)-div(outer)-body-html-document。
DOM2级的注册事件和解除事件
在DOM2级中使用addEventListener和removeEventListener来注册和解除事件(IE8及之前版本不支持)。这种函数较之之前的方法好处是一个dom对象可以注册多个相同类型的事件,不会发生事件的覆盖,会依次的执行各个事件函数。
- addEventListener(‘事件名称’,’事件回调’,’捕获/冒泡’)。
示例如下:
<div id = 'outer' style = 'margin: 100px 0 0 100px; width: 200px;height: 200px; background: red;'>
<div id="inner" style = 'margin-left:20px; width: 50px;height:50px; background: green;'></div>
</div>
<script>
var click = document.getElementById('inner');
click.addEventListener('click',function(){
alert('click one');
},false);
click.addEventListener('click',function(){
alert('click two');
},false);
</script>
首先我们要知道addEventListenr的第一个参数是事件名称,与DOM0级不同的是没有”on“,另外第三个参数代表捕获还是冒泡,true代表捕获事件,false代表冒泡事件。
而在这段代码中,我们为inner的div注册了两个click事件函数,结果是浏览器会依次执行这两个函数。
我们在开发的时候需要兼顾IE与非IE浏览器,所以注册一个监听器应该这样写:
var a = document.getElementById('a');
if(a.attachEvent){
a.attachEvent('onclick',func);
}
else{
a.addEventListener('click',func,false);
}
停止事件冒泡和阻止事件的默认行为
停止事件冒泡
停止事件冒泡是指,停止冒泡型事件的进一步传递(取消事件传递,不只是停止IE和DOM标准共有的冒泡型事件,我们还可以停止支持DOM标准浏览器的捕捉型事件,用stopPropagation()方法)。例如上图中的冒泡型事件传递中,在body处理停止事件传递后,位于上层的document的事件监听器就不再收到通知,不再被处理。
- 在IE下,通过设置event对象的cancelBubble为true即可。
function someHandle() {
window.event.cancelBubble = true;
}
- DOM标准通过调用event对象的stopPropagation()方法即可。
function someHandle(event) {
event.stopPropagation();
}
- 因此,跨浏览器的停止事件传递的方法是:
function someHandle(event) {
event = event || window.event;
if(event.stopPropagation){
event.stopPropagation();
}else {
event.cancelBubble = true;
}
}
阻止事件的默认行为
停止事件的默认行为是指,通常浏览器在事件传递并处理完后会执行与该事件关联的默认动作(如果存在这样的动作)。例如,如果表单中input type 属性是 “submit”,点击后在事件传播完浏览器就自动提交表单。又例如,input 元素的 keydown 事件发生并处理后,浏览器默认会将用户键入的字符自动追加到 input 元素的值中。
- 在IE下,通过设置event对象的returnValue为false即可。
function someHandle() {
window.event.returnValue = false;
}
- DOM标准通过调用event对象的preventDefault()方法即可。
function someHandle(event) {
event.preventDefault();
}
- 因此,跨浏览器的取消事件传递后的默认处理方法是:
function someHandle(event) {
event = event || window.event;
if(event.preventDefault){
event.preventDefault();
}else{
event.returnValue = false;
}
}
总结
- 完整的事件处理兼容性函数
var EventUtil = {
addHandler: function(element, type, handler){
if (element.addEventListener){
element.addEventListener(type, handler, false);
} else if (element.attachEvent){
element.attachEvent("on" + type, handler);
} else {
element["on" + type] = handler;
}
},
removeHandler: function(element, type, handler){
if (element.removeEventListener){
element.removeEventListener(type, handler, false);
} else if (element.detachEvent){
element.detachEvent("on" + type, handler);
} else {
element["on" + type] = null;
}
},
getEvent: function(event){
return event ? event : window.event;
},
getTarget: function(event){
return event.target || event.srcElement;
},
preventDefault: function(event){
if (event.preventDefault){
event.preventDefault();
} else {
event.returnValue = false;
}
},
stopPropagation: function(event){
if (event.stopPropagation){
event.stopPropagation();
} else {
event.cancelBubble = true;
}
};
详情推荐网站:http://blog.csdn.net/chenmoquan/article/details/10162477