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://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。