细说 jQuery 事件篇(三) – 事件传播
Javascript
是如何决定由哪个元素来处理事件的,以及 jquery
又是如何优化处理这个问题的,这些都涉及到了事件传播。
事件传播策略
当页面内的发生一个事件时,每个层次的 DOM
元素都有机会来处理这个事件,为了弄懂整个过程,举例说明:
<div class="wrapper">
<span class="bar">
<a href="#">segmentfault</a>
</span>
</div>
1.事件捕获
有两种策略来处理事件,第一种是事件捕获。
当采取“事件捕获”策略时,点击 a
标签后,事件首先交给外层的元素,然后再往内交给更具体的元素:
div -> span -> a
2.事件冒泡
另一种策略是“事件冒泡”,事件冒泡与事件捕获刚好相反,当点击 a
标签后,首先会发送到最具体的元素,在这个元素得到响应后,事件会往上冒泡到更外层的元素:
a -> span -> div
一开始,不同的浏览器采用不同的策略来处理事件传播,为了统一化,DOM
标准规定应该同时使用着两种策略,首先通过“事件捕获”来捕获到最具体的元素,接着通过“事件冒泡”返回到 DOM
树的顶层。
3.统一策略
同时,我们很容易理解,对于事件的处理程序既可以发生在事件捕获阶段,也可以发生在事件冒泡阶段,jQuery
为了统一策略决定始终在事件冒泡阶段注册事件处理程序。因此,我们可以假定最具体最内层的元素会首先获得响应事件的机会。
事件冒泡的弊端
事件冒泡可能会导致意料之外的行为,例如在响应 mouseout
事件时,依旧是上例,当为最外层的 div
添加一个 mouseout
事件。此时,如果鼠标移出 div
区域时,肯定会触发 mouseout
事件绑定的程序,这是我们期望的,但是如果鼠标是从 a
元素上离开时,a
元素也会取得一个 mouseout
事件,再通过事件冒泡后,外层的 div
也会获得,这显然不是我们想要的。
给 div
添加样式来便于区分:
div {
width: 200px;
height: 200px;
background-color: lightblue;
}
绑定 mouseout
事件到 div
上:
$('div').mouseout(function() {
//触发 `alert`
alert('mouse is out!');
});
当鼠标从淡蓝色的区域移开时,触发 alert
,但是当鼠标放到 a
标签上后再移开,即使没移开 div
区域,同样也会触发 alert
,这显然不是我们希望的,这就是事件冒泡带来的弊端。
这里介绍两种直接简单的方法来解决这个问题。
第一是使用 jQuery
自带的 .hover()
方法,.hover()
方法接受两个函数参数,第一个参数在鼠标进入绑定元素时执行,第二个参数在鼠标移除绑定元素时执行。使用 .hover()
方法可以避免事件传播导致的问题。
$('div').hover(function() {}, function() {
alert('mouse is out!');
});
第二种方法是使用 mouseleave
来代替 mouseout
方法。
$('div').mouseleave(function() {
//触发 `alert`
alert('mouse is out!');
});
这两种方法是针对 mouseout
可能出现的问题来解决的,对于事件冒泡可能导致的其他弊端现象,我们需要用更加适用的方法来解决,因为这个知识点在书中的下一个章节介绍,所以我打算在下一篇博文中总结。
参考
http://book.douban.com/subject/24669823/
您可能感兴趣的文章:
细说 jQuery 事件篇(四) – 改变事件过程
细说 jQuery 事件篇(三) – 事件传播
jQuery源码分析系列
解密jQuery事件核心 – 委托设计(二)
细说 jQuery 事件篇(二) – 处理简单事件
jQuery代码优化 事件委托篇
解密jQuery事件核心 – 自定义设计(三)
jQuery 2.0.3 源码分析 事件绑定 – bind/live/delegate/on
事件冒泡是什么如何用jquery阻止事件冒泡
细说 jQuery Ajax操作篇(一) – 数据加载