【转】event.cancelBubble与event.stopPropagation()

来源:互联网 发布:什么是大数据应用 编辑:程序博客网 时间:2024/05/14 07:31

转载自:http://blog.csdn.net/lhy2199/article/details/7221442

 

event.stopPropagation()

Description: Prevents the event from bubbling up the DOM tree, preventing any parent handlers from being notified of the event. 

  • version added:1.0event.stopPropagation()
    We can use event.isPropagationStopped() to determine if this method was ever called (on that event object).

    This method works for custom events triggered withtrigger(), as well.

   Note that this will not prevent other handlerson the same element from running.

Additional Notes:

  • Since the .live() method handles events once they have propagated to the top of the document, it is not possible to stop propagation of live events. Similarly, events handled by.delegate() will propagate to the elements to which they are delegated; event handlers bound on any elements below it in the DOM tree will already have been executed by the time the delegated event handler is called. These handlers, therefore, may prevent the delegated handler from triggering by callingevent.stopPropagation() or returningfalse.

Example:

Kill the bubbling on the click event.

$("p").click(function(event){  event.stopPropagation();  // do something});  

Support and Contributions

Need help with event.stopPropagation() or have a question about it? Visit thejQuery Forum or the#jquery channel on irc.freenode.net.

Think you've discovered a jQuery bug related to event.stopPropagation()? Report it to the jQuery core team.

Found a problem with this documentation? Report it to the jQuery API team.

由于HTML中的对象都是层次结构,比如一个Table包含了多个TR,一个TR包含了多个TD,Bubble就是一个事件可以从子节点向

父节点传递,比如鼠标点击了一个TD,当前的event.srcElement就是这个TD,但是这种冒泡机制使你可以从TR或者Table处截

获这个点击事件,但是如果你设置此td的event.cancelBubble=true,则就不能上传事件,即tr和table的点击事件不响应td

的点击事件。比如下面的例子:onclick="tableA_rowA_click事件会同时引起tableA的onclick事件,而tableA_rowB_click

阻止了事件冒泡则不会引起tableA的事件。这不是一个标准性的属性,FF不支持,IE支持,其它浏览器未测。
<html>
    <body>
    <table border="1" width="26%" id="tableA" onclick="alert('点击了tableA')">
        <tr onclick="tableA_rowA_click()">
            <td width="106">一般</td>
        </tr>
        <tr onclick="tableA_rowB_click(event)">
            <td width="106">阻止消息上传</td>
        </tr>
    </table>
    </body>
< /html>


< script language="javascript">
    function tableA_rowA_click(){  
        alert('点击了tableA的rowA');  
    }  

    function tableA_rowB_click(event){  
        alert('点击了tableA的rowB');  
        event.cancelBubble=true;  
    }  
< /script>
在IE的事件机制中,触发事件会从子元素向父元素逐级上传,就是说,如果子元素触发了单击事件,那么也会触发父元素的

单击事件;event.cancelBubble=true;可以停止事件继续上传。FF中事件也是从子元素向父元素逐级上传,但FF不支持

event.cancelBubble,FF支持stopPropagation()方法。将上面的方法改为:
function tableA_rowB_click(event){  
        alert('点击了tableA的rowB');  
event.stopPropagation();
    }
则和IE中的效果是一样的。可以这样写一个方法兼容:
function stopBubble(event) {
//如果提供了事件对象,则这是一个非IE浏览器
if (event.stopPropagation)
//因此它支持W3C的 stopPropagation()方法
event.stopPropagation();
else
//否则,我们需要使用IE的方式来取消事件冒泡
event.cancelBubble = true;
}

首先我在网上看到不少文章大体上分为两个(不正确)观点:

1. cancelBubble用于ie的阻止冒泡事件,event.stopPropagation()用于firefox和chrome等其他浏览器。

先不讲上面是对是错

先看一个例子:(测试环境:chrom5.0.275.7,  moz3.6.4,   opera10.53,   ie6,7,8)

代码

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
   
<title>无标题页</title>
</head>
<body onclick="alert('body');">

   
<input id="Button1" type="button" value="button" onclick="clickBtn(event)"/>
   
<script language="javascript" type="text/javascript">
       
function clickBtn(event)
        {
            event
=event?event:window.event;
            event.cancelBubble
=true;
            alert(event.cancelBubble);
        }
   
</script>
</body>
</html>
复制代码

经过测试:

a,chrom5.0.275.7,   opera10.53,   ie6,7,8在这几个浏览器中  , cancelBubble是有效的,并且可以阻止事件冒泡,使body的onclick不能触发。只触发button的click

alert(event.cancelBubble);输出结果true

b,在  moz3.6.4版本内,是不能阻止body的onclick的,但是alert(event.cancelBubble);输出结果仍然是true ,我想这应该是event.cancelBubble只是给event添加一个属性,并且赋值为true;

当把js代码改成这样时:

代码
<!--

Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/

-->   <script language="javascript" type="text/javascript">
       
function clickBtn(event)
        {
            event
=event?event:window.event;
            event.stopPropagation();
            alert(
"123");
        }
   
</script>
复制代码

即可有效阻止。当然在chrome,opera中的 event.stopPropagation();也是有效的,

结论一:以上说明 event.cancelBubble在新版本chrome,opera浏览器中已经支持,就差moz了,其实个人认为event.cancelBubble比event.stopPropagation()更好,不仅从英文意思上。所以希望moz再发新版本  也支持。这样就兼容了

2.还有就是经常看的关于事件顺序的问题:

不完全准确的结论(自认为

ie:源事件元素->>父级元素事件->>body-->>document

moz:等其他浏览器与上面相反

先看一个例子:

代码
<!--

Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/

--><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
   
<title>无标题页</title>
</head>
<body onclick="alert('body');">

   
<div onclick="clickBtn(event)"  style="width:100px;height:100px; background:#666;">
       
<input id="Button1" type="button" value="button" onclick="alert('btn');"/>
   
</div>
   
<script language="javascript" type="text/javascript">
       
function clickBtn(event)
        {
            event
=event?event:window.event;
            event.stopPropagation();
            alert(
"123");
        }
   
</script>
</body>
</html>
复制代码

如果按照上面的观点   我现在点击button    事件从  body---->div----->button,,,,那么就是 先alertbody然后再触发div弹出123,由于阻止冒泡,所以button的click不会触发。

但经过我们测试。moz还是按照由内向外触发。正确的执行alert("btn")--->>alert("123")----阻止冒泡  不触发body的click事件

到这你是不是会怀疑上面不正确,不过上面的讲法对用addListenter和attachEvent添加的事件是正确的()。如:

代码
<!--

Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/

--><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
   
<title>无标题页</title>
</head>
<body>

  
<ul id='ul'>
           
<liid='li1'>List Item1</li>
           
<liid='li2'>List Item2</li>
   
</ul>
   
<script language="javascript" type="text/javascript">
           
function init(){
            
if(!!document.all){
                document.getElementById(
'li1').attachEvent('onclick',function(event){
                    alert(
'li1');
                }) 
                document.getElementById(
'li2').attachEvent('onclick',function(event){
                    alert(
'li2');
                })
                document.getElementById(
'ul').attachEvent('onclick',function(event){
                    alert(
'ul');
                   
//event.cancelBubble = true;
                    alert(event.stopPropagation);
                }); 
             }
else{
                document.getElementById(
'li1').addEventListener('click',function(event){
                    alert(
'li1');
                },
true)
                document.getElementById(
'li2').addEventListener('click',function(event){
                    alert(
'li2');
                },
true)
                document.getElementById(
'ul').addEventListener('click',function(event){
                     event
=event?event:window.event;
                     event.stopPropagation();
                     alert(
'ul');
                },
true);
                 
              }
            } 
            init();
   
</script>
</body>
</html>
复制代码

用这种方法 是符合的。执行结果是触发ul的click事件然后由于阻止了冒泡所以此时你点击li时,其本身的click事件不触发。(顺便说一句,用这种动态添加事件的方法,好像event.cancelBubble在moz中也有效了不过在chrome和moz中有区别