欢迎来到 jackNEss'窝窝
I like simple mind

探讨事件冒泡

2011年10月08日

探讨事件冒泡

如果你是通过搜关键字搜到这篇文章的话,估计你是在开发的过程中遇到了事件冒泡不好的一面,并在寻求阻止事件冒泡的方法,本文将从事件冒泡原理说起,阐述事件冒泡好的一方面和不好的一面,并提供如何在不想事件冒泡的时候进行阻止。

what’s mean by 事件冒泡(Event Bubble)

在一个对象 a (这里用 a 表示该对象) 上触发某个事件(如 onclick事件),如果对象 a 定义了触发事件对应的函数function,那么 对象 a 就会调用这个函数,如果没定义触发此事件对应的函数或者事件返回 true 的话,那么这个事件就会向对象 a 的父级对象传播,从里到外,直至它被处理(父级对象所有同类事件都将被激活),或者它到达了DOM 的最上顶层,即 document对象。我们将这种现象称之为事件冒泡。

以下是关于事件冒泡的例子:

<!-- html -->
<div class="parent" onclick = "alert('I\'m parent')">
	<div class="child" onclick = "alert('I\'m child')">点我试试</div>
	点我试试
</div>

样式如图所示:

当我们点击白色区域的时候,毫无悬念,触发parent 的 onclick事件,弹出提示框 “I’m parent”。

但是,当我们点击 灰色部分的时候,除了触发 child 本身的 onclick事件 弹出提示框 “I’m child” 之外,还触发了 parent 的 onclick事件。

演示地址:http://www.jackness.org/lab/bubble/demo01.html

事件冒泡的作用

其实事件冒泡不单只在 javascript 中会存在,很多编译语言如 C++,C#等都早已引入,不算是什么新技术新概念,一般情况下,事件冒泡其实还是蛮好的,利用冒泡可以让事件挂钩更干净,有效减小内存开销。

允许多个操作被集中处理

事件冒泡允许多个操作被集中处理(把事件处理器添加到一个父级元素上,避免把事件处理器添加到多个子级元素上),它还可以让你在对象层的不同级别捕获事件。

我这里拿提交数据为例,功能是无论 onclick 哪一个都执行 datasubmit()函数,以下是相关html代码:

<div>
	<div>点我可以提交</div>
	<div>点我可以提交</div>
	<div>点我可以提交</div>
	<div>点我可以提交</div>
</div>	

如果没有事件冒泡处理,实现这一功能,我们得向每个 子级元素添加onclick事件:

<div onclick ="datasubmit()">
	<div onclick ="datasubmit()">点我可以提交</div>
	<div onclick ="datasubmit()">点我可以提交</div>
	<div onclick ="datasubmit()">点我可以提交</div>
	<div onclick ="datasubmit()">点我可以提交</div>
</div>

但是如果有了 事件冒泡机制的话,我们就只需要给父级元素添加 onclick事件 就ok了:

<div onclick ="datasubmit()">
	<div>点我可以提交</div>
	<div>点我可以提交</div>
	<div>点我可以提交</div>
	<div>点我可以提交</div>
</div>

让事件并行发生

让不同的对象同时捕获同一事件,并调用自己的专属处理程序做自己的事情,就像老板一下命令,各自员工做自己岗位上的工作去了。

举个简单的例子,只要点击 a3元素,那么 a1,a2各自绑定的事件都能同时执行了。

<div id="a1" onclick = "sendCellphoneNumber();">
	<div id="a2" onclick ="send3size();">
		<div id="a3" onclick = "sendMsg();">点我试试</div>
	</div>
</div>

事件冒泡的顺序

Netscape 的冒泡顺序是从最顶层开始冒泡,一直到事件源,而其他浏览器则相反,是从事件源开始,一直冒泡到最顶层。

例如:

<div id="a1" onclick = "sendCellphoneNumber();">
	<div id="a2" onclick ="send3size();">
		<div id="a3" onclick = "sendMsg();">点我试试</div>
	</div>
</div>

Netscape 冒泡顺序是:a1,a2,a3;
而其他浏览器 的冒泡顺序是:a3,a2,a1;

事件冒泡的坏处

事件冒泡的坏处,最常见的表现就是 onmouseover 、 onmouseout问题了,当对象 a 已经设置了 这2种事件处理函数的时候,每当鼠标经过对象 a 的子对象的时候,恭喜,每经过一次,这个 对象 a 对应的 onmouseover 和 onmouseout 就触发一次,这并不是我们想得到的结果。具体例子在实现 onmouseenter 和 onmouseleave 中会为大家展现。

阻止事件冒泡

不想发生事件冒泡的时候,当然,是可以阻止的,IE提供了 cancelBubble 属性,如果将其设为 true,即可阻止事件冒泡;而其他浏览器则采用 stopPropagation() 方法,只要调用此方法,同样可以阻止事件冒泡。

cancelBubble

IE 为每个 DOM元素 提供了 cancelBubble 属性,当设为true的时候 事件冒泡就会被阻止。

//stop bubble for IE
function stopBubbleForIE(e){
	e = e||window.event;
	e.cancelBubble = true;
}

用法

var elm = document.getElementById("elm");
elm.onclick = function(){
	alert("hello jack!");
	stopBubbleForIE();
}

stopPropagation()

非IE浏览器提供了 stopPropagation() 方法,只要调用此方法,即可阻止事件冒泡。

//stop bubble for other bowser
function stopBubble(e){
	e = e||window.event;
	e.stopPropagation();
}

用法

var elm = document.getElementById("elm");
elm.onclick = function(){
	alert("hello jack!");
	stopBubble();
}

兼容所有浏览器的 阻止事件冒泡方法

其实也就是将上述2种方法进行整合。

//阻止事件冒泡
function stopBubble(e){
		
	e = e||window.event;
	if( typeof e.cancelBubble != "underfined"){
		e.cancelBubble = true;
		
	}
	else if( e.stopPropagation ){
		
		e.stopPropagation();
	}
}	

演示地址:http://www.jackness.org/lab/bubble/demo02.html

分类javascript
阅读 1,495
  • 评论加载中...

标签云

分类目录

最新留言

  • 评论加载中...

与我联系

如有疑问or建议可通过以下方式跟我取得联系.

Q Q:373435871
Email:jackness1208@gmail.com
© Copyright 2011 - 2014 jackNEss.org All Rights Reserved 粤ICP备14065612号
首页 | 关于我 | 网站地图 | RSS