本文共 4400 字,大约阅读时间需要 14 分钟。
文章转自 http://woshao.com/article/809b72f4132311e081e3000c295b2b8d/ 1.什么是事件冒泡: 页面上有好多事件,也可以多个元素响应一个事件.假如: <BODY οnclick="alert('aaa');"> <div οnclick="alert('bbb');"> <a href="#" class="cooltip" title="这是我的超链接提示1。" οnclick="alert('ddd');> 提示 </a> </div> </BODY> 上面这段代码一共有三个事件,body,div,a都分别绑定了单击事件。在页面中当单击a标签会连续弹出3个提示框。这就是事件冒泡引起的现象。事件冒 泡的过程是:a –> div –> body 。a冒泡到div冒泡到body 事件的冒泡有什么好处呢? 想象一下现在我们有一个10列、100行的HTML表格,你希望在用户点击表格中的某一单元格的时候做点什么。比如说我有一次就需要让表格中的每一个单元格在被点击的时候变成可编辑状态。如果把事件处理器加到这1000个单元格会产生一个很大的性能问题,并且有可能导致内存泄露甚至是浏览器的崩溃。相反地,使用事件代理的话,你只需要把一个事件处理器添加到table元素上就可以了,这个函数可以把点击事件给截下来,并且判断出是哪个单元格被点击了。 代码很简单,我们所要关心的只是如何检测目标元素而已。比方说我们有一个 table元素,ID是“report”,我们为这个表格添加一个事件处理器以调用editCell函数。editCell函数需要判断出传到table 来的事件的目标元素。考虑到我们要写的几个函数中都有可能用到这一功能,所以我们把它单独放到一个名为getEventTarget的函数中: function getEventTarget(e) { e = e || window.event; return e.target || e.srcElement; } e这个变量表示的是一个事件对象,我们只需要写一点点跨浏览器的代码来返回目标元素,在IE里目标元素放在srcElemtn属性或event.toElement属性中,而在其它浏览器里则是target或event.relatedTarget属性。 接下来就是editCell函数了,这个函数调用到了 getEventTarget函数。一旦我们得到了目标元素之后,剩下的事情就是看看它是否是我们所需要的那个元素了。 function editCell(e) { var target = getEventTarget(e); if(target.tagName.toLowerCase() === 'td') { // DO SOMETHING WITH THE CELL } } 在editCell函数中,我们通过检查目标元素标签名称的方法来确定它是否是一个表格的单元格。这种检查也许过于简单了点;如果它是这个目标元素单元格里的另一个元素呢?我们需要为代码做一点小小的修改以便于其找出父级的td 元素。如果说有些单元格不需要被编辑怎么办呢?此种情况下我们可以为那些不可编辑的单元格添加一个指定的样式名称,然后在把单元格变成可编辑状态之前先检查它是否不包含那个样式名称。选择总是多样化的,你只需找到适合你应用程序的那一种。 需要注意的是: 如果你的代码处理mousemove事件的话你遇上性能瓶颈的风险可就大了,因为mousemove事件触发非常频繁。而mouseout则因为其怪异的表现而变得很难用事件代理来管理。 如何避免事件冒泡: /*--------------------------- 功能:停止事件冒泡 ---------------------------*/ function stopBubble(e) { //如果提供了事件对象,则这是一个非IE浏览器 if ( e && e.stopPropagation ) //因此它支持W3C的stopPropagation()方法 e.stopPropagation(); else //否则,我们需要使用IE的方式来取消事件冒泡 window.event.cancelBubble = true; } //阻止浏览器的默认行为 function stopDefault( e ) { //阻止默认浏览器动作(W3C) if ( e && e.preventDefault ) e.preventDefault(); //IE中阻止函数器默认动作的方式 else window.event.returnValue = false; return false; } 使用方法 //监视用户何时把鼠标移到元素上, //为该元素添加红色边框 unionDom[i].onmouseover = function(e) { this.style.border = "1px solid red"; stopBubble( e ); }; //监视用户何时把鼠标移出元素, //删除我们所添加的红色边框 unionDom[i].onmouseout = function(e) { this.style.border = "0px"; stopBubble( e ); }; uniconDom[i]是页面的一个html标记 阻止jQuery事件冒泡 jQuery对DOM的事件触发具有冒泡特性。有时利用这一特性可以减少重复代码,但有时候我们又不希望事件冒泡。这个时候就要阻止jQuery.Event冒泡。 在jQuery.Event的文档中的开头得知,jQuery.Event对象是符合W3C标准的一个事件对象,同时jQuery.Event免去了检查兼容IE的步骤。 jQuery.Event提供了一个非常简单的方法来阻止事件冒泡:event.stopPropagation(); $("p").click(function(event){ event.stopPropagation(); // do something }) 但是这个方法对使用live绑定的事件没有作用,需要一个更简单的方法阻止事件冒泡:return false; $("p").live("click", function(){ $(this).after("Another paragraph!"); return false; }); 最后给出一个完整的事件冒泡前后对比的例子: <!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" lang="zh" xml:lang="zh"> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <meta name="developer" content="Realazy" /> <title>Bubble in JavaScript DOM</title> <style type="text/css" media="screen"> div * {display:block; margin:4px; padding:4px; border:1px solid white;} textarea {width:20em; height:2em;} </style> <script type="text/javascript"> //<![CDATA[ function init(){ var log = document.getElementsByTagName('textarea')[0]; var all = document.getElementsByTagName('div')[0].getElementsByTagName('*'); for (var i = 0, n = all.length; i < n; ++i){ all[i].onmouseover = function(e){ this.style.border = '1px solid red'; log.value = '鼠标现在进入的是: ' + this.nodeName; }; all[i].onmouseout = function(e){ this.style.border = '1px solid white'; }; } var all2 = document.getElementsByTagName('div')[1].getElementsByTagName('*'); for (var i = 0, n = all2.length; i < n; ++i){ all2[i].onmouseover = function(e){ this.style.border = '1px solid red'; if (e) //停止事件冒泡 e.stopPropagation(); else window.event.cancelBubble = true; log.value = '鼠标现在进入的是: ' + this.nodeName; }; all2[i].onmouseout = function(e){ this.style.border = '1px solid white'; }; } } window.onload = init; //]]> </script> </head> <body> <h1>Bubble in JavaScript DOM</h1> <p>DOM树的结构是:</p> <pre><code> UL - LI - A - SPAN </code> Bubbllllllllllllllle Bubbllllllllllllllle 鼠标进入UL的任何一个子元素,如果不停止冒泡,我们从UL到SPAN都定义了鼠标悬停(mouseover)事件,这个事件会上升了UL,从而从鼠标所进入的元素到UL元素都会有红色的边。 Bubbllllllllllllllle Bubbllllllllllllllle 如果停止冒泡,事件不会上升,我们就可以获取精确的鼠标进入元素。转载地址:http://akgmi.baihongyu.com/