[JS]笔记12之事件机制--事件冒泡和捕获--事件监听--阻止事件传播

-->事件冒泡和捕获
-->事件监听
-->阻止事件传播

一、事件冒泡和捕获

1、概念:当给子元素和父元素定义了相同的事件,比如都定义了onclick事件,点击子元素时,父元素的onclick事件也会被触发。js里称这种事件连续发生的机制为事件冒泡或者事件捕获。
IE浏览器:事件从里向外发生,事件从最精确对象(target)开始触发,然后到最不精确的对象(document)触发,即事件冒泡

Netscape:事件从外向里发生,事件从最不精确的对象(document)开始触发,然后到最精确对象(target)触发,
事件捕获


2、W3C标准将两者进行中和,在任何的W3C的事件模型中,
事件先进入捕获阶段,再进入冒泡阶段

3、一般的绑定事件方式
div1.onclick=function () {
alert('div被点击');
};
在一个支持W3C DOM的浏览器中,一般的绑定事件方式,采用的是事件冒泡方式

程序员可以选择绑定事件时采用事件捕获还是事件冒泡,
办法就是绑定事件时通过addEventListener( )方法


二、事件监听

1、支持W3C标准的浏览器在绑定事件时可以用addEventListener(type,fn,useCapture) 方法
参数:type----------事件类型,例:click
   fn--------------事件处理函数
   useCapture----布尔值true或false
( true表示事件捕获,false表示事件冒泡 )
为了兼容浏览器,第三个参数一般设置为false

事件监听:addEventListener(type,fn,useCapture) 

事件移除:removeEventListener(type, fn, useCapture)

2、因为IE678只支持事件冒泡,不支持事件捕获,所以它也不支持addEventListener( )方法,IE提供了另一个函数:

attachEvent( type , fn )
参数:type---------事件类型,例:onclick
   fn-------------事件处理函数
没有第三个参数

事件监听:attachEvent( type , fn )

事件移除:detachEvent( type , fn )

三、阻止事件传播

事件冒泡事件捕获都有传播的特征
阻止事件传播的方法:
在W3C中使用 Event.stopPropagation();
在IE中使用 Event.cancelBubble=true;

var Event=ev||window.event;
if (Event.stopPropagation){
Event.stopPropagation();//非IE阻止事件传播
}else{
Event.cancelBubble=true;//IE阻止事件冒泡
}

四、阻止默认事件

var Event=ev||event;
if (Event.preventDefault) {
Event.preventDefault(); //非IE阻止默认事件
} else{
Event.returnValue=false; //IE阻止默认事件
};

return false; 代码中遇到立即停止执行,跳出正在执行的函数,相当于终止符,可以用来阻止默认事件
PS:注意使用位置,不能滥用

五、代码

组织事件传播示例:

 1 <!DOCTYPE html>
 2 <html lang="en">
 3 <head>
 4 <meta charset="UTF-8">
 5 <title>阻止事件传播</title>
 6 <style>
 7 *{margin:0;padding:0;list-style: none;}
 8 ul{500px;height:300px;background: #ccc;}
 9 li{300px;height:150px;background: pink;}
10 p{100px;height:100px;background:blue;}
11 </style>
12 </head>
13 <body>
14     <ul>
15         <li>
16             <p></p>
17         </li>
18     </ul>
19 <script>
20     var ul=document.getElementsByTagName('ul')[0];
21     var li=document.getElementsByTagName('li')[0];
22     var p=document.getElementsByTagName('p')[0];
23     ul.onclick=function(){
24         alert('我是ul');
25     }
26     li.onclick=function(ev){
27         alert('我是li');
28         var e=window.event||ev;
29         if (e.stopPropagation) {//组织事件传播到父级
30             e.stopPropagation();
31             //非IE阻止事件传播(W3C)
32         } else {
33             e.cancelBubble=true;
34             //IE阻止事件传播(IE)
35         }
36     }
37     p.onclick=function(){
38         alert('我是p');
39     }
40 
41 </script>
42 </body>
43 </html>

自定义右击菜单练习:

 1 <!DOCTYPE html>
 2 <html lang="en">
 3 <head>
 4 <meta charset="UTF-8">
 5 <title></title>
 6 <style>
 7 *{margin:0;padding:0;}
 8 div{150px;height:300px;background: pink;display:none;position: absolute;}
 9 span{color:red;}
10 </style>
11 </head>
12 <body>
13 <div>
14     <span>第一页</span>
15     <span>下一页</span>
16     <span>刷新</span>
17 </div>
18 <script>
19     var div=document.getElementsByTagName('div')[0];
20     document.oncontextmenu=function(ev){//菜单右击事件
21         div.style.display='block';
22         var e=window.event||ev;
23         if(e.preventDefault){//组织默认右击事件
24             e.preventDefault();
25         }else{
26             e.returnValue=false;
27         }
28         var winH=document.documentElement.clientHeight;
29         var winW=document.documentElement.clientWidth;
30         var divH=div.offsetHeight;
31         var divW=div.offsetWidth;
32         var x=e.clientX;
33         var y=e.clientY;
34         if (winH-y<divH) {
35             div.style.top=(y-divH)+'px';
36         } else {
37             div.style.top=y+'px';
38         }
39         if (winW-x<divW) {
40             div.style.left=(x-divW)+'px';
41         } else {
42             div.style.left=x+'px';
43         }
44         
45     }
46 </script>
47 </body>
48 </html>
原文地址:https://www.cnblogs.com/paulirish/p/bubbleandpropagation.html