js事件详解

事件流
DOM事件流的三个阶段:1、事件捕获阶段 2、处于目标阶段 3、事件冒泡阶段
要理解事件流我们先来看一看事件的整个传播过程:
  事件捕获阶段:用户触发事件window-->document-->html-->body-->祖先节点-->.......-->父节点-->目标元素
  事件冒泡阶段:目标元素-->父节点-->......->祖先节点-->body-->html-->document-->window
所有的浏览器都实现了事件冒泡(网景除外)。
IE9+和所有的现代浏览器也都支持事件捕获并且是从window开始捕获的。
NOTE:由于低版本IE(IE8-)不能实现事件捕获,因此很少用。
事件处理程序
响应某个事件的处理函数就是事件处理程序。
1、html事件处理程序
1 <input type="button" value="单击事件" oncick="fnHandler()" />

NOTE:在html事件处理程序中使用双引号、大于、小于等符号时可以使用实体符代替。

1 <button onclick="fnShow(&quot;hello&quot;)">单击事件</button>
2 <script>
3     function fnShow(sMsg){
4         alert(sMsg);
5     }
6 </script>

缺点:

  1、时差问题。当事件处理程序代码放在元素的后面,在事件处理程序没有解析完成用户就出发了事件就会报错;

  2、html代码和javascript代码耦合比较高。

2、DOM0级事件处理程序

  将函数赋值给元素的事件处理程序属性

1     var oBtn = document.getElementById('btn');
2     oBtn.onclick = function(){
3         alert('clicked');
4     }

  删除DOM0级事件处理程序,就是将该事件处理属性设置为null。

1     var oBtn = document.getElementById('btn');
2     oBtn.onclick = function(){
3         alert('clicked');
4     }
5     oBtn.onclick = null;

3、DOM2级事件处理程序

  DOM2级事件处理程序提供了两个方法:addEventListener和removeEventListener。他们包含三个参数:事件名、事件处理函数、布尔值(true捕获、false冒泡).

1     var oBtn = document.getElementById('btn');
2     oBtn.addEventListener('click', function(){
3         alert('clicked');
4     }, false);

  好处:可以给同一个事件添加多个事件处理函数。

1     var oBtn = document.getElementById('btn');
2     oBtn.addEventListener('click', function(){
3         alert('clicked');
4     }, false);
5     oBtn.addEventListener('click', function(){
6         alert('clicking');
7     }, false);

  通过addEventListener添加的事件处理程序只能通过removeEventListener来删除。

NOTE:通过addEventListener添加的匿名函数不能被reomveEventListener删除。

1     // 添加的和删除的不是同一个函数。在堆内存中不一样。
2     var oBtn = document.getElementById('btn');
3     oBtn.addEventListener('click', function(){
4         alert('clicked'); // 任然会执行
5     }, false);
6     oBtn.removeEventListener('click', function(){
7         alert('clicked');
8     }, false);

4、IE8-事件处理程序

  IE8-实现了DOM类似的两个事件处理方法:attachEvent()、detachEvent()。通过这两个方法只能添加事件到冒泡阶段。

1     var oBtn = document.getElementById('btn');
2     oBtn.attachEvent('onclick', function(){ // 事件名前要加on
3         alert('clicked');
4     });

NOTE:使用attachEvent添加事件时的执行作用域是全局作用域。

1     var oBtn = document.getElementById('btn');
2     oBtn.attachEvent('onclick', function(){ 
3         alert(this == window); // true
4         alert('clicked');
5     });
6     oBtn.addEventListener('click', function(){
7         alert(this == window); // false
8         alert('clicked');
9     }, false);

NOTE:在IE9、10中任然保留了这两个方法并且可以和addEventListener叠加事件,不能相互删除对应事件,IE11+已经没有这两个方法了。

 1     var oBtn = document.getElementById('btn');
 2     oBtn.attachEvent('onclick', fnHandler); // 添加
 3     oBtn.removeEventListener('click', fnHandler, false); // 删除
 4     function fnHandler(){
 5         alert('clicked'); // 任然执行
 6     }
 7     oBtn.addEventListener('click', fnHandler1, false); // 添加
 8     oBtn.detachEvent('onclick', fnHandler1); // 删除
 9     function fnHandler1(){
10         alert('clicked1'); // 任然执行
11     }

NOTE:attachEvent(先添加后执行)添加多个事件时与addEventListener(先添加先执行)事件执行顺序相反。在IE8-中是这样的,但是在IE9、10中却是先添加先执行。

 1     var oBtn = document.getElementById('btn');
 2     oBtn.attachEvent('onclick', function(){
 3         alert('attach1');
 4     });
 5     oBtn.attachEvent('onclick', function(){
 6         alert('attach2');
 7     });
 8 
 9     oBtn.addEventListener('click', function(){
10         alert('add1');
11     });
12     oBtn.addEventListener('click', function(){
13         alert('add2');
14     });
跨浏览器的事件处理程序实现
首先检查DOM2级事件处理程序、再检测IE事件处理程序、最后通过DOM0级事件处理程序。
 1     var oBtn = document.getElementById('btn');
 2     var EventUtil = {
 3         addHandler: function(oDom, sEventType, fnHandler){
 4             if(oDom.addEndEventListener){
 5                 oDom.addEndEventListener(sEventType, fnHandler, false);
 6             }else if(oDom.attachEvent){
 7                 oDom.attachEvent('on' + sEventType, fnHandler);
 8             }else{
 9                 oDom['on' + sEventType] = fnHandler;
10             }
11         },
12         removeHandler: function(oDom, sEventType, fnHandler){
13             if(oDom.removeEndEventListener){
14                 oDom.removeEndEventListener(sEventType, fnHandler, false);
15             }else if(oDom.detachEvent){
16                 oDom.detachEvent('on' + sEventType, fnHandler);
17             }else{
18                 oDom['on' + sEventType] = null;
19             }
20         }
21     }
跨浏览器的事件对象
 1     var EventUtil = {
 2         // 绑定事件
 3         addHandler: function(oDom, sEventType, fnHandler){
 4             if(oDom.addEndEventListener){
 5                 oDom.addEndEventListener(sEventType, fnHandler, false);
 6             }else if(oDom.attachEvent){
 7                 oDom.attachEvent('on' + sEventType, fnHandler);
 8             }else{
 9                 oDom['on' + sEventType] = fnHandler;
10             }
11         },
12         // 解除事件
13         removeHandler: function(oDom, sEventType, fnHandler){
14             if(oDom.removeEndEventListener){
15                 oDom.removeEndEventListener(sEventType, fnHandler, false);
16             }else if(oDom.detachEvent){
17                 oDom.detachEvent('on' + sEventType, fnHandler);
18             }else{
19                 oDom['on' + sEventType] = null;
20             }
21         },
22         // 获取事件对象
23         getEvent: function (event) {
24             return event ? event : window.event;
25         },
26         // 获取事件目标元素
27         getTarget: function(event){
28             return event.target || event.srcElement;
29         },
30         // 阻止默认事件
31         preventDefault: function(event){
32             if(event.preventDefault){
33                 event.preventDefault();
34             }else{
35                 event.returnValue = false;
36             }
37         },
38         // 阻止事件冒泡
39         stopPropagation: function(event){
40             if(event.stopPropagation){
41                 event.stopPropagation();
42             }else{
43                 event.cancelBubble = true;
44             }
45         }
46     }

 

posted @ 2015-02-16 21:58  tyxloveyfq  阅读(276)  评论(0编辑  收藏  举报