事件流
事件流描述的是从页面中接收事件的顺序。
1.事件冒泡:
IE的事件流叫做事件冒泡,即就是从一个具体的元素开始逐层向上传递到较为不具体的元素直至文档。通过下面的例子来看一下:
<!DOCTYPE html>
<html>
<head>
<title>事件冒泡</title>
</head>
<body>
<div id='box'>Click me</div>
</body>
</html>
当你点击页面的div元素时,这个click事件会按照如下顺序传播:
- div
- body
- html
- document
2.事件捕获:
事件捕获的思想是较为不具体的节点更早的接收到事件,而最具体的元素最后接收事件。如果仍是上面的例子,当我们点击div元素时,这个click事件会按照如下顺序传播:
- document
- html
- body
- div
3.DOM事件流
“DOM2级事件”规定的事件流包括三个阶段:事件捕获阶段,事件目标阶段,事件冒泡阶段。
仍以前面的例子来说,在DOM事件流中,实际的目标(div)在捕获阶段不会接收到事件。这就意味着在捕获阶段,事件从document到html到body后就停止了。下一个阶段是目标阶段,于是事件在div上发生。然后冒泡阶段发生,事件传播回文档。
事件处理程序
1.HTML事件处理程序
简单来说,HTML事件处理程序就是将你要处理的事件直接放在元素内部了。比如:
function show(){
alert('zhangmengying');
}
<input type = 'button' value = 'Click me' onclick = 'show()'>
这样指定事件处理程序会创建一个封装着元素属性值的函数。这个函数中有一个局部变量event。
<input type = 'button' value = 'Click me' onclick = 'alert(event.type)'>
这时就会输出click。
通过event变量,可以直接访问事件对象。在这个函数内部,this值等于事件的目标元素,比如:
<input type = 'button' value = 'Click me' onclick = 'alert(this.value)'>
这时会输出Click me。
在HTML中指定事件处理程序的缺点在于:
- 存在时差问题。以我们的第二个例子来说,当我们的show()函数是在页面的底部定义的,而我们的input是在页面的开始就定义了。那么当页面刚加载我们就触发相应的事件,但是在这个时候函数有可能还不具备这个条件。
- HTML和JS具有强耦合性。
2.DOM0级事件处理程序
每个元素都具有自己的事件处理程序属性,例如onclick。将这种属性的值设置为一个函数,就可以指定事件处理程序,例如;
var btn = document.getElementById('box');
btn.onclick = function(){
alert('zhangmengying');
}
使用DOM0级方法指定的事件处理程序被认为是元素的方法,也就是说,这时this的值就是当前元素。例如:
var btn = document.getElementById('box');
btn.onclick = function(){
alert(this.id);
}
这时的输出为box。
以这种方式添加的事件处理程序会在事件流的冒泡阶段被处理。
也可以删除通过DOM0级方法指定的事件处理程序,只需要将事件处理程序设置为null即可。例如:
btn.onclick = null;
将事件设置为null之后,再点击就不会发生任何动作。
3.DOM2级事件处理程序
DOM2级事件处理程序使用addEventListener()方法来指定事件处理程序。所有的DOM节点都包含这个方法。这个方法接受三个参数:
- 要处理的事件类型(不含有on,例如click)
- 事件处理程序函数
- 是否捕获。布尔值,true为捕获,false为不捕获。
如果要在上面的例子中添加DOM2级事件处理程序:
var btn = document.getElementById('box');
btn.addEventListener('click',function(){
alert(this.id);
},fasle);
在这段代码中,this值为当元素,即div。
使用DOM2级事件处理程序的主要好处在于可以添加多个事件处理程序。比如:
var btn = document.getElementById('box');
btn.addEventListener('click',function(){
alert(this.id);
},fasle);
btn.addEventListener('click',function(){
alert(‘张梦莹’);
},fasle);
添加的这两个事件会按照指定的顺序执行。
通过addEventListener()添加的事件处理程序只能使用removeEventListener()来移除;移除时传入的参数和添加时传入的参数相同。这也就意味着removeEventListener()无法移除匿名函数。
4.IE事件处理程序
IE添加事件处理程序使用attchEvent()。这个方法接受两个参数:
- 要处理的事件类型(含有on,例如onclick)
- 事件处理程序函数
如果要在上面的例子中添加IE事件处理程序:
var btn = document.getElementById('box');
btn.addEvent('o'clock',function(){
alert('zhangmengying');
}
在IE中使用attchEvent()与使用DOM0级方法的主要区别在于事件处理程序的作用域。
在使用DOM0级方法的情况下,事件处理程序会在其所属元素的作用域内运行;在使用attchEvent()方法的情况下,事件处理程序会在全局作用中运行,此时this值为window。
与addEventListener()类似,attchEvent()也可以添加多个事件处理程序。但是不同的是attchEvent()添加的事件处理程序的执行顺序与指定的顺序是相反的。
使用attchEvent()添加的事件使用detachEvent()来移除。参数与attchEvent()相同,同样也不能移除匿名函数。
5.跨浏览的事件处理程序
为了实现在不能浏览器下实现相同的效果,必须兼容处理事件。代码如下:
var EventUtil = {
addEvent:function(element, type,handler){
if(element.addEvnetListener){
element.addEvnetListener(type, handler,false);
}else if(element.attchEvent){
element.attchEvent(type, handler);
}else{
element['on'+type] = handler;
}
};
removeEvent:function(element, type,handler){
if(element.removeEvnetListener){
element.removeEvnetListener(type, handler,false);
}else if(element.detachEvent){
element.detachEvent(type, handler);
}else{
element['on'+type] = null;
}
};
}
下面我们来调用一下这个方法:
var btn = document.getElementById('box');
var handler = function(){
alert('大功告成');
}
EventUtil.addEvent(btn, 'click',handler);
...
EventUtil.removeEvent(btn, 'click',handler);
今天就到这里啦,关于事件的其他内容我会再接下来的几天继续更新!