在了解事件模型之前先简单的谈下事件流: JS事件流最早要从IE和网景公司的浏览器大战说起,IE提出的是冒泡流,而网景提出的是捕获流,后来在W3C组织的统一之下,JS支持了冒泡流和捕获流,但是目前低版本的IE浏览器还是只能支持冒泡流(IE6,IE7,IE8均只支持冒泡流),所以为了能够兼容更多的浏览器,建议大家使用冒泡流。
JS事件流原理图如下:
从图中我们可以知道
1、一个完整的JS事件流是从window开始,最后回到window的一个过程
2、事件流被分为三个阶段(1~5)捕获过程、(5~6)目标过程、(6~10)冒泡过程
事件类型 | 捕获过程 | 冒泡过程 |
DOM Level 0 | 不支持 | 支持 |
DOM Level 2 | 支持 | 支持 |
IE | 不支持 | 支持 |
事件类型:DOM Level 0(原始事件类型)、DOM Level 2、IE事件类性
一、DOM0模型
直接在dom上绑定事件(例如onclick),没有事件的传播(事件一旦发生就立刻调用事件句柄)。
特点:
1、DOM0级事件模型是早期的事件模型,所有的浏览器都是支持的。
2、一个DOM对象只能注册一个同类型的函数,因为注册多个同类型的函数的话,就会发生覆盖,之前注册的函数就会无效。
3、DOM0不会阻止事件冒泡的发生
下面举个例子:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<link rel="stylesheet" href="./css/event.css">
</head>
<body>
<div id="parent">
<div id="child"></div>
</div>
<script type="application/javascript" src="js/event.js"></script>
</body>
</html>
var child = document.getElementById('child')
var parent = document.getElementById('parent')
// 注册事件
child.onclick = function (event) {
console.log('child')
}
parent.onclick = function (event) {
console.log('parent')
}
// 执行结果
child
parent
--------------------------------------------------------------------------
--------------------------------------------------------------------------
// 接触事件方法
child.onclick = null
parent.onclick = null
二、DOM2模型
DOM2级中使用addEventListener和removeEventListener来注册和解除事件(IE8及之前版本不支持这种事件注册),同时支持事件流的捕获过程和冒泡过程,通过addEventListener('事件名称','事件回调','捕获/冒泡')第三个参数的设置,制定事件句柄的触发是在捕获过程还是冒泡过程(默认false即冒泡)。 如果要移除事件句柄,addEventListener() 的执行函数必须使用外部函数。匿名函数,类似 "document.removeEventListener("event", function(){ myScript });" 该事件是无法移除的。
特点:
1、IE8及之前版本不支持这种事件注册。
2、一个dom对象可以注册多个相同类型的事件,不会发生事件的覆盖,会依次的执行各个事件函数。
例子:
// 注册事件,设置触发句柄在捕获阶段
var parentEvent = function () {
console.log('parent')
}
child.addEventListener('click', function (event) {
console.log('child')
}, true)
parent.addEventListener('click', parentEvent, true)
// 结果
parent
child
// 移除事件
parent.removeEventListener('click', parentEvent, true)
三、IE模型
标准的浏览器绑定事件是addEventListener,解除绑定是removeEventListener,而在ie8以及之前的版本中绑定事件是attachEvent,解除绑定是detachEvent,attachEvent仅支持在冒泡阶段触发句柄,所以该方法只有两个参数。
特点:
1、IE浏览器都支持这种事件注册。
2、一个dom对象可以注册多个相同类型的事件,不会发生事件的覆盖,会依次的执行各个事件函数。
3、仅在冒泡阶段触发句柄
4、事件前加on (例如 onclick)
例子:
// 注册事件
child.attachEvent('onclick', function () {
alert('child')
})
parent.attachEvent('onclick', function () {
alert('parent')
})
四、兼容处理
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;
}
}
};