一、事件流
事件流描述的是从页面接受事件的顺序,但是目前有两个概念,而且正好相反。IE的事件流是事件冒泡,Netscape Communicator的事件流是事件捕获。
1、1事件冒泡
这是IE的事件流,即是事件从文档中嵌套最深的那个结点开始接受,然后依次传播到最为不具体的结点。
<div style="background-color: red;width: 200px ;height: 200px;">
<div style="background-color: yellow;width: 100px;height: 100px">
click
</div>
</div>
如上代码,则先接受到事件的是背景为yellow的div,其次才是red的那个div。事件顺序为:
yellow div->red div ->body ->Element->Document
1.2、事件捕获
事件捕获则正好与事件冒泡相反,还是上面的代码,最先接受到事件的是
Document->Element->body->red div -> yellow div
1.3、DOM事件流
“DOM2级事件”规定的事件流包括3个阶段:
- 事件捕获
- 处于目标阶段
事件冒泡阶段
这第一个和第三个分别对应了前面介绍的两个,中间那个则是我们处理事件的时候。
二、事件处理程序
事件处理程序就是因用户或者浏览器自身执行的某种动作而响应的某个函数。
2.1 HTML事件处理程序
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<input type="button" value="点我" onclick="doSomeThing()">
<script>
function doSomeThing() {
alert("do some thing")
}
</script>
</body>
</html>
事件处理程序的代码在执行时,有权访问全局作用域中的任何代码。
注意:上面指定事件处理程序会创建一个event变量。
2.2、DOM0级事件处理
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<input type="button" value="click me" id="btn">
<script>
var btn = document.getElementById("btn");
btn.onclick = function () {
alert("clicked");
}
</script>
</body>
</html>
DOM0级方法指定的事件处理程序被认为是元素的方法,这个时候事件处理程序是在元素的作用域中运行,也就是说this指定是当前元素.
这种方法添加的事件处理程序会在事件流的冒泡阶段被处理。
// 删除DOM0级指定的事件处理程序
btn.onclick = null
删除HTML事件将对应的onclick属性指定为null即可。
2.3DOM2级事件处理程序
DOM2级事件定义了两个方法
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<input type="button" value="click me" id="btn">
<script>
var btn = document.getElementById("btn");
btn.addEventListener("click", function () {
alert("Hello");
}, false);
btn.addEventListener("click",function () {
alert("World");
},false);
</script>
</body>
</html>
与DOM0级不同的是,DOM2级主要好处是可以添加多个事件处理程序,事件触发按照它们添加的顺序。
该方法的第三个bool值的参数为true:表示在捕获阶段调用事件处理程序,为false表示在冒泡阶段调用事件处理程序。
这里添加的事件处理程序也是其衣服的元素的作用域中运行,和DOM级一样。
// 删除事件处理
btn.removeEventListener("click",fn);
注意:这里的第二个参数必须是一个方法名,也就是说不能删除匿名函数的事件。
2.4、IE事件处理程序
IE中有两个和DOM类似的方法
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<input type="button" value="click ie" id="btn">
<script>
var btn = document.getElementById("btn");
btn.attachEvent("onclick", function () {
alert("clicked");
});
</script>
</body>
</html>
与DOM不同的是,IE事件处理的第一个参数是”onclick”而不是”click”.
注意:使用attachEvent()方法,事件处理程序在全局作用域中运行,这里的this相当于window。
和DOM2级类似,attachEvent方法也支持为一个元素添加多个事件处理。不过疑惑的是,这些事件的处理是按照添加顺序的相反执行的。
2.5、跨浏览器的事件处理程序
/**
* Created by lw on 2017/1/26.
*/
var EventUtil = {
/**
* 添加事件处理
* @param element
* @param type
* @param handler
*/
addHandler: function (element, type, handler) {
if (element.addEventListener) { // 如果是Dom二级事件
element.addEventListener(type, handler, false);
} else if (element.attachEvent) { // 如果是IE事件处理
element.attachEvent(type, handler);
} else {
element["on" + type] = handler; // dom0级
}
},
/**
* 移除事件处理
* @param element
* @param type
* @param handler
*/
removeHandler: function (element, type, handler) {
if (element.removeEventListener) {
element.removeEventListener(type, handler, false);
} else if (element.detachEvent) { // 如果是IE事件处理
element.detachEvent(type, handler);
} else {
element["on" + type] = null; // dom0级
}
}
}
当然,该工具类并不完善,例如前面提过的IE中事件处理的作用域的问题,不过使用其添加移除事件也足够了。