在 《细说 jQuery 事件篇(三) - 事件传播》 中提到了事件冒泡可能造成的弊端,当时举了 mouseout
的例子,对于 mouseout
这个特殊情况,我们可以用 hover
方法来解决,但是对于 hover
方法无法解决的情形,我们又应该如何处理呢?
为此,我们必须通过访问事件对象来改变事件过程。
事件对象是一种
DOM
结构,它会在元素获得处理事件的机会时传递给调用的事件处理程序。这个对象中包含着与事件有关的信息。
事件对象 event
的 target
属性指的是事件目标,它将保存发生事件的目标元素。
首先,我们举一个 hover
无法处理的例子:
<div class="wrapper">
<span class="bar">
<a href="http://segmentfault.com" target="_blank">segmentfault</a>
</span>
</div>
样式为:
div {
width: 200px;
height: 200px;
border: 1px solid #ccc;
}
我们的需求是仅仅当点击 div
区域时添加一个背景色,但是点击 a
标签时并不改变背景色。
添加样式为:
.blueBg {
background-color: lightblue;
}
jQuery
代码为:
$('div').click(function() {
$('div').addClass('blueBg');
});
此时点击 div
后:
但由于事件冒泡的存在,当我们点击 a
标签跳出页面后,发现 div
的背景色也被改变。所以,接下来我们就要想办法改变事件过程来阻止这个行为。
阻止事件冒泡
利用事件对象的 .stopPropagation()
方法可以阻止事件冒泡。下面我们来阻止 a
标签向上冒泡。修改 jQuery
代码如下:
$('a').click(function(event) {
event.stopPropagation();
});
$('div').click(function(event) {
$('div').addClass('blueBg');
});
此时,再点击 a
标签将不会改变 div
的背景色。
但是根据 jQuery
文档的说明,stopPropagation
方法对 live
和 delegate
绑定的事件是不支持的。
阻止默认行为
如果此时我们还希望能阻止 a
标签的默认行为,也就是打开一个页面的行为,这里我们需要用到事件对象的 .preventDefault()
方法。
$('a').click(function(event) {
event.preventDefault();
event.stopPropagation();
});
$('div').click(function(event) {
$('div').addClass('blueBg');
});
此时,点击 a
标签不仅不会改变 div
的背景色,也不会打开新的页面,也就是说默认行为被阻止。
事件委托
曾经写过一篇介绍事件委托的博文 - 《Javascript - 事件委托是怎么工作的?》。这里就不详细写了,但是 jQuery
提供了专门的方法来实现事件委托,就是利用 .on()
方法。
对于之前博文的例子:
<ul id="parent-list">
<li id="post-1">Item 1</li>
<li id="post-2">Item 2</li>
<li id="post-3">Item 3</li>
<li id="post-4">Item 4</li>
<li id="post-5">Item 5</li>
<li id="post-6">Item 6</li>
</ul>
<script>
// 获得父级元素并添加 click 事件监听
document.getElementById("parent-list").addEventListener("click",function(e) {
// e.target 即 click 事件发生的元素,同时判断该元素是否是一个 li 标签
if(e.target && e.target.nodeName == "LI") {
// console 输出被点击的 li 标签的 id
console.log("List item ",e.target.id," was clicked!");
}
});
</script>
利于 jQuery
的 on
方法可以简写为:
<ul id="parent-list">
<li id="post-1">Item 1</li>
<li id="post-2">Item 2</li>
<li id="post-3">Item 3</li>
<li id="post-4">Item 4</li>
<li id="post-5">Item 5</li>
<li id="post-6">Item 6</li>
</ul>
<script type="text/javascript">
$(function() {
$('#parent-list').on('click', 'li', function(e) {
console.log("List item ",e.target.id," was clicked!");
})
});
</script>
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。