jquery阻⽌事件冒泡的两种⽅法
事件的旅程:
jquery弹出div窗口当页⾯上发⽣⼀个事件时,每个层次上的DOM元素都有机会处理这个事件。以下⾯的页⾯模型为例:
1. <div class="foo">
2. <span class="bar">
3. 下午茶-⽹页前端
4. </span>
5.<p>jquery事件冒泡-下午茶-⽹页前端</p>
6. </div>
当在浏览器中形象化地呈现这些由嵌套的代码构成的元素时,我们看到的效果其实是这样的。
DOM模型
举例来说,如果单击了页⾯中的超链接(锚元素),那么</p><div>、<span>和 全都应该得到响应这次单击的机会。
毕竟,这三个元素都同时处于⽤户的⿏标指针之下啊。
允许多个元素响应单击事件的⼀种策略叫做“事件捕获”。在事件捕获的过程中,事件⾸先会交给最外层的元素,接着再交给更具体的元素。在这个例⼦中,意味着单击事件⾸先会传递给</p><div>,然后是<span>,最后是</span>,如下⾯:
事件捕获
另⼀种相反的策略叫做“事件冒泡”。即当事件发⽣时,会⾸先发送给最具体的元素,在这个元素获得响应机会之后,事件会向上冒泡到更⼀般的元素。在我们的例⼦中,会⾸先处理事件,然后按照顺序依次是<span>和<div>,如下图所⽰:
事件冒泡
毫不奇怪,不同的浏览器开发者们最初采⽤的是不同的事件传播模型。因⽽,最终出台的DOM标准规定应该同时使⽤这两种策略:⾸先,事件要从⼀般到具体进⾏捕获,然后,事件再通过冒泡返回DOM树的顶层。⽽事件处理程序可以注册到这个过程中的任何⼀部分。
但是,遗憾的通知⼤家,浏览器⼚商,并不是这么做的。。
并不是所有浏览器都为了与新标准保持⼀致⽽进⾏了更新,⽽且,对于那些⽀持捕获的浏览器来说,通常必须明确启⽤才⾏。为了提供跨浏览器的⼀致性,jquery始终会在事件模型的冒泡阶段注册事件处理程序。因此,我们总是可以假定最具体的元素会⾸先获得响应事件的机会。
备注:FireFox运载标准事件模型(即同时⽀持捕获和冒泡),要把事件处理注册到捕获阶段,必须在标准的事件注册⽅法addEventListener()中将最后⼀个参数设置为true。
IE的事件注册⽅法attachEvent()只能将事件处理程序注册到冒泡阶段。
为了提供跨浏览器兼容性,jQuery始终会在模型的冒泡阶段注册事件处理程序(即为了和IE兼容啊。。),因此,我们总是可以假定最具体的元素会⾸先获得响应事件的机会。
事件冒泡带来的问题:
例⼦:
1. <div id="switcher">
2. <h3>style switcher</h3>
3. <div id="switcher-normal" class="button selected">normal</div>
4. <div id="switcher-narrow" class="button">narrow column</div>
5. <div id="switcher-large" class="button">large print</div>
6. </div>
点击查看原始尺⼨
在上⾯的例⼦中说明了事件冒泡可能会导致问题的情形。
javascript部分:
1. $(document).ready(function(){
2. $('#switcher').click(function(){
3. alert("aaaa")
4. })
5. });
上⾯的代码会使#switcher整个区域都可以通过单击触发事件运⾏alert命令,但是我们并不希望在#switcher⾥⾯的三个class=button的div单击时也运⾏alert,只是希望在黄⾊的区域响应单击事件并运⾏alert。
导致这个问题的原因是:事件冒泡,即事件⾸先通过class=button的div处理,然后⼜沿着DOM树向上传递,直⾄到达
阻⽌事件冒泡
⽅法⼀:event.target == this
要解决这个问题,必须访问事件对象(Event对象)。事件对象是⼀种javascript结构,它会在元素获得处理事件的机会时被传递给相应的事件处理程序,这个对象中包含着与事件有关的信息(例如事件发⽣时的⿏标指针位置),也提供了可以⽤来影响事件在DOM中传递进程的⼀些⽅法。
为了在处理程序中使⽤事件对象(Event对象),需要为函数添加⼀个参数:
$('#switcher').click(function(event){....});
事件⽬标
现在,事件处理程序中的变量event保存着事件对象。⽽event.target属性(不过在IE中,是使⽤event.srcElement)保存着发⽣事件的⽬标元素,即DOM中最⾥⾯最具体的元素,这个属性是DOM API中的规定的,但IE没有按照标准把事件对象传递给事件处理程序,⽽是把事件对象保存在全局属性window.event中,通过srcElement属性访问。但在jquery中,已经解决了这个浏览器兼容问题,统⼀使⽤“event.target属性”就可以了。如果在javascript中,你可以这样引⽤event.target来解决浏览器兼容问题:
var target=( (event.srcElement) ? event.srcElement : event.target )
通过event.target,可以确定DOM中⾸先接收到事件的元素(即实际被单击的元素),⽽且,我们知道this引⽤的是处理事件的DOM元素,所以可以使⽤以下代码:
1. $(document).ready(function(){
2. $('#switcher').click(function(event){
3. if(event.target == this){ alert("aaa") }
4. })
5. }};
此时,代码确保了单击的元素是
,⽽不是其后代元素,现在单击class=button的div就不弹出alert了,⽽只会在单击黄⾊区域才会alert
⽅法⼆:停⽌事件的传播 event.stopPropagation()
事件对象还提供了⼀个event.stopPropagation()的⽅法,该⽅法可以完全阻⽌事件冒泡,与event.target类似,这个⽅法也是⼀种纯javascript特性,但在跨浏览器的环境中则⽆法完全地使⽤,不过,只要我们通过jquery来注册所有的事件处理程序,就可以放⼼使⽤这个⽅法了。
继续以上⾯的例⼦,同样的html结构,
如果去除(event.target==this)这个判断句的话,在上⾯的原代码的基础上,那么可以增加以下代码来阻⽌事件冒泡
代码为:
1. $(document).ready(function(){
2. $('#switcher .button').click(function(event){
3. event.stopPropagation();
4. })
5. })
同前⾯的⼀样,需要为⽤作单击处理程序的函数添加⼀个参数,以便访问事件对象,然后,通过简单地调⽤event.stopPropagation()就可以避免其他所有DOM元素响应这个事件了。这样⼀来,在class=button的div上单击按钮的事件就会被按钮处理,⽽且只会被按钮处理,只有单击黄⾊区域才会发⽣alert,因为在button处单击已经被阻⽌了冒泡到最外层的div上。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论