你的位置:首页 > Java教程

[Java教程]浅谈JS事件冒泡


       今天要跟大家谈的是事件冒泡,这个事件呢,也是两面性的,有时候给我们带来bug,有时候优点也很明显。我们就一起来看看它的真面目。

 首先看看事件冒泡是什么?

 事件冒泡 :当一个元素接收到事件的时候 会把他接收到的事件传给自己的父级,一直到window 。(注意这里传递的仅仅是事件 并不传递所绑定的事件函数。所以如果父级没有绑定事件函数,就算传递了事件 也不会有什么表现 但事件确实传递了。)

只看这句话,或许不是那么好理解,下面来看个栗子:

var div1 = document.getElementById("div1");var div2 = document.getElementById("div2");  div2.onclick = function(){alert(1);};  div1.onclick = function(){alert(2);};//父亲//html代码 <div id="div1">  <div id="div2"></div> </div>

 

代码很简单,就是两个父子关系的div,然后分别加了点击事件,当我们在div2里面点击的时候,会发现弹出了一次1,接着又弹出了2,这说明点击的时候,不仅div2的事件被触发了,它的父级的点击事件也触发了,这种现象就叫做冒泡。点击了div1,自己父级的点击事件也会被触发。

再看个栗子

 

var div1 = document.getElementById("div1");var div2 = document.getElementById("div2") 

div1.onclick = function(){alert(2);}; // 父亲
//html代码 <div id="div1"> <div id="div2"></div> </div>

 

大家可以看一下效果图,相比于第一个例子,代码已经把儿子的点击事件去掉,只留下了父级的,测试的结果是当只点击了儿子,会弹出2,由此证明了当点击了儿子,父亲的点击事件被触发,执行了自己绑定的函数。由于一些人会以为显示出来儿子在父亲里面的时候,自然点了儿子相当于点了父亲,所以这个例子我故意把两个盒子绝对定位在了两个不同的位置,所以点击事件给页面显示出来的位置是没关系的,而是跟html代码中的位置有关系。

 

可能有人会有疑惑下面这种情况,为啥没有弹出两次:

var div1 = document.getElementById("div1");
var div2 = document.getElementById("div2");  div2.onclick = function(){alert(1);};  div1.onclick = function(){}; //父亲//html代码 <div id="div1">  <div id="div2"></div> </div>

这里我们要注意,我们传递的仅仅是事件触发,也就是说当点击div2仅仅触发了父级的点击事件,并没有把自己的绑定的函数给父级,父级的执行情况,取决于自己所绑定的函数,因为在这里它绑定的函数是空,自然没什么表现。有些人在这里有误解,所以强调一下。

以上大概就是冒泡的形式了,而大多数时候,冒泡也带来了一些困扰,下面我们看一个栗子:

我们的需求是点击上面红色的面板让下面粉色的面板显示,点击其他地方再让粉丝面板隐藏。于是我们会这样写js代码:

<script>var div2 = document.getElementById("div2");var div1 = document.getElementById("div1"); div2.onclick = function(){  //红色面板事件    div1.style.display = "block";  }; document.onclick = function(){   div1.style.display = "none"; }</script>

这个时候我们测试发现,怎么点击红色面板,粉丝面板都不会显示了,为什么呢?就是冒泡的原因,我们来分析下代码,当点击div2的时候,他会触发父亲级别的点击事件,然后一层一层的往上传,所以document的点击事件自然也被触发了,然后执行了自己身上的绑定事件,让粉色面板消失。所以当你点击div2的时候首先,让粉丝面板显示,只是事件执行太快了,很快又执行了document的点击事件,让面板隐藏。 有兴趣的可以再两个事件之间加一个弹出,就可以测试。

那么这个时候我们肯定不希望有冒泡了,所以解决办法就是取消冒泡了:

这个时候需要用到事件对象里的 cancelBubble属性,把它设为true即可,ev.cancelBubble=true;所以改进后的代码如下:

<script>var div2 = document.getElementById("div2");var div1 = document.getElementById("div1"); div2.onclick = function(ev){ // 红色面板加事件   var ev = ev || window.event; //因为不同浏览器支持不一样,所以需要兼容,关于事件对象,可以自行查阅,之后也会在博客更新。   div1.style.display = "block";   ev.cancelBubble=true; //这样就不会再冒泡给父级了 }; document.onclick = function(){   div1.style.display = "none"; }</script>

 其实冒泡还有一大优点,而且经常用到,还能提高很大的性能,想要了解,下回分解,我们沐晴,下回不见不散。