Professional javascript For Web Developers 第2版读书笔记第5集event事件
事件流(event flow)
如果一张纸上有一组同心圆(我们可以认为是大圆嵌套着小圆),当你用手指放在纸的中间(圆心), 我们应该认为你所碰到的不仅仅是哪一个圆,而是所有的圆,因为你的手指处在所有圆的范围内,也就是说你不光指向了最里面的圆,同时指向了它的容器(大圆认为是容器,小圆嵌套在里面),然后向上递归。
同样的道理,如果你在页面上点击了一个按钮,那就不仅仅是点击了这个按钮,也同时点击了这个按钮所在的容器 。
IE和 Netscape Communicator实现事件流的方式不一样。IE是冒泡流(Event Bubbling),而Netscape Communicator是捕捉流(event capturing flow)
冒泡流是从最具体的元素开始向上冒泡依次触发相应的事件。如
< head >
< title > Event Bubbling Example < /title >
< /head >
< body >
< div id=”myDiv” > Click Me < /div >
< /body >
< /html >
单击div元素的时候,div元素的click事件会被触发,然后依次按照dom树的顺序向上触发
IE5.5及之前的版本会跳过HTML元素,即从body直接跳到Document元素。Firefox,Chrome,Safari均实现冒泡事件流,并按刚才的顺序递归一直到window对象。
而捕捉流与冒泡流顺序相反
Firefox,Chrome,Safari也支持捕捉流,并且从window对象开始捕捉,然而DOM2的标准中事件应该从document开始
DOM事件流
此方式定义在DOM2的规格说明中,包括3个阶段:捕获event capturing,触发目标hit the target,冒泡 Event Bubbling
DOM2中定义捕获阶段不触发目标,拿上面的例子来说从document到body后此截断便停止。
然而Safari, Chrome, Firefox, and Opera 9.5以及后续版本都在捕获截断会触发目标,意味着有2次机会来和目标交互。同时IE不支持DOM event flow
DOM0事件处理
事件处理作为元素element的一种属性存在,可以直接指派处理函数,同时时间处理函数的作用域都是元素本身,因此this指向的是当前元素
如:
btn.onclick = function(){
alert(“Clicked”);
};
移除事件处理程序
DOM2事件处理
addEventListener() 和 removeEventListener() 方法注册和移除处理函数。它们都接受3个参数分别为:事件名,处理函数,一个bool类型指明是在捕获流中还是在冒泡流中调用事件处理程序,true表示在捕获流,false表示在冒泡流。
使用addEventListener()还可以为某个事件注册多个处理程序,按照他们注册的顺序一次执行,如
btn.addEventListener(“click”, function(){
alert(this.id);
}, false);
btn.addEventListener(“click”, function(){
alert(“Hello world!”);
}, false);
同时用addEventListener()注册的处理函数必须用removeEventListener()才可以移除,但是此处理函数不能是匿名函数,因为没有指针指向此匿名函数,如
btn.addEventListener(“click”, function(){//事件名没有on前缀,这和DOM0不同
alert(this.id);
}, false);
//other code here
btn.removeEventListener(“click”, function(){ //won ’ t work!
alert(this.id);
}, false);
虽然这2个匿名函数内容一样,但是它们不是同一个函数。
要实现移除
var handler = function(){
alert(this.id);
};
btn.addEventListener(“click”, handler, false);
//other code here
btn.removeEventListener(“click”, handler, false); //works!
IE事件处理
IE通过attachEvent()和detachEvent()来绑定和移除处理函数,ie仅支持冒泡流,这些方法仅2个参数:事件名、处理函数
btn.attachEvent(“onclick”, function(){
alert(“Clicked”);
});
与DOM0方式不同,attachEvent绑定的函数运行的作用域是全局的即window对象,而不是所绑定给的元素对象。
btn.attachEvent(“onclick”, function(){
alert(this === window); //true
});
attachEvent也可以绑定多个处理函数,但是当调用的时候执行的顺序和绑定的顺序相反
btn.attachEvent(“onclick”, function(){
alert(“Clicked”);
});
btn.attachEvent(“onclick”, function(){
alert(“Hello world!”);
//先弹出hello world 然后弹出clicked
移除处理程序detachEvent,使用方式和DOM中的removeEventListener一样,也是注意不要使用匿名函数
注意,要避免使用dom0+dom2或者dom0+ie(attachevent)混合的方式
dom0+dom2混合的方式注册处理函数,那么函数执行的顺序跟它们注册的顺序相同
obj.addEventListener('mousedown',Func2,false);
obj.addEventListener('mousedown',Func3,false);
obj.onmousedown=Func1;
如果是IE+DOM0,始终先执行DOM0方式注册的函数,然后attachEvent中注册的函数按照逆序(类似桟的后进先出)执行
//obj.onmousedown=Func1;
obj.attachEvent('onmousedown',Func2);
//obj.onmousedown=Func1;
obj.attachEvent('onmousedown',Func3);
obj.onmousedown=Func1;//无论DOM0方式在哪注册,最后都是在事件触发的时候最先执行
因此要避免这种混合使用的方式,它会给浏览器兼容性带来很大的麻烦
Event对象
不论DOM0还是DOM2中事件处理函数都能传递一个event参数,此参数包括了关于此事件的相关信息,需要注意的事,必须显式的才处理函数中声明event,代码才可以访问到event的属性和函数,当然参数的名不一定非要是"event",任何符合规范的参数名都可以
btn.onclick = function(event){
alert(event.type); //”click”
};
btn.addEventListener(“click”, function(event){
alert(event.type); //”click”
}, false);
与event相关的函数和 (此表显示的是所有类型元素再触发事件时event对象拥有的)
如果事件处理程序是直接指派给相应的元素,那么event对象的target和currentTarget指向触发此事件的元素,同时this在函数内部也指向同样的元素,如:
btn.onclick = function(event){
alert(event.currentTarget === this); //true
alert(event.target === this); //true
};
如果处理处理函数被注册到触发元素的父节点上,情况有所不同
alert(event.currentTarget === document.body); //true
alert(this === document.body); //true
alert(event.target === document.getElementById(“myBtn”)); //true
};
this和currentTarget指向了注册此事件的元素document.body,而target指向真正触发此事件的元素button,因为此button没有指派事件处理程序,因此单击事件被冒泡到了document.body来处理。
preventDefault用来阻止默认的行为,如链接元素a被单击的时候会导向一个新页面,如果要阻止这样的行为
link.onclick = function(event){
event.preventDefault();
};
那些 cancelable为true的元素才可以通过preventDefault来取消默认行为
stopPropagation()函数用来取消事件流的扩散,可以取消捕获流或者冒泡流
eventPhase表示处理程序处于哪个事件流中,1标识捕获流,2标识at the target,3标识事件流,值得注意的是尽管"at the target"处于冒泡阶段,但它的eventPhase=2
btn.onclick = function(event){
alert(event.eventPhase); //2
};
document.body.addEventListener(“click”, function(event){
alert(event.eventPhase); //1
}, true);
document.body.onclick = function(event){
alert(event.eventPhase); //3
};
event仅在事件处理函数中存在,当处理函数执行完毕,event对象偏会销毁
posted on 2010-08-04 10:34 MoonWalker 阅读(236) 评论(0) 编辑 收藏 举报