1

《细说 jQuery 事件篇(三) - 事件传播》 中提到了事件冒泡可能造成的弊端,当时举了 mouseout 的例子,对于 mouseout 这个特殊情况,我们可以用 hover 方法来解决,但是对于 hover 方法无法解决的情形,我们又应该如何处理呢?
为此,我们必须通过访问事件对象来改变事件过程。

事件对象是一种 DOM 结构,它会在元素获得处理事件的机会时传递给调用的事件处理程序。这个对象中包含着与事件有关的信息。

事件对象 eventtarget 属性指的是事件目标,它将保存发生事件的目标元素。
首先,我们举一个 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 方法对 livedelegate 绑定的事件是不支持的。

阻止默认行为

如果此时我们还希望能阻止 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>

利于 jQueryon 方法可以简写为:

<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://book.douban.com/subject/24669823/


StephenLi
7k 声望488 粉丝

知不足。