2

我被一些事件监听器困住了。单击一个元素时,我想为单击创建另一个侦听器。出于某种原因,他们都在开火。这是代码和 jsbin:http: //jsbin.com/uHIyiGi/2/edit HTML

<div class="wrap">
 <button>Click me</button>
</div>

JS

$('button').on('click', function(event){
  $('body').append('<p>button clicked</p>');
  $('.wrap').addClass('clicked');

  $('body').on('click', '.clicked', function(e){
    $('body').append('<p>.clicked clicked</p>');
    $('.wrap').removeClass('clicked');
    $('body').off('click', '.clicked');
  });
});

根据我对事件侦听器的了解,在“.clicked”元素具有完整的单击事件(鼠标按下和鼠标向上)之前,第二个不应该触发,但它会在第一次单击时触发,这意味着即使触发了该事件直到事件之后,该元素才具有触发器类。我每次都看到事件侦听器成功删除,但在我认为应该调用它之前就调用了它。所以,我现在真的很困惑......有什么建议吗?我希望我在不久的将来有一个手掌。

4

1 回答 1

5

事件泡沫。当您单击按钮时,您正在向正文添加一个事件。一旦按钮的事件处理程序完成(意味着包装现在有一个 clicked 类),它就会继续冒泡 DOM 直到它到达主体。由于正文现在有一个新的单击事件,因此也会触发该事件。然后,jQuery 在正文中查找与选择器匹配的元素.clicked,并在找到的任何元素上调用处理程序。要停止这种情况,您可以使用 setTimeout 延迟将事件绑定到主体,或者在按钮的单击事件上停止传播,这样它就不会冒泡到主体。

$('button').on('click', function(event){
    event.stopPropagation();
    ...

时间线:

  1. 触发 mousedown 事件,然后在按钮上同时触发 mouseup 事件
  2. 单击事件处理程序在按钮上触发
  3. clicked类被添加到.wrapdiv
  4. 点击事件绑定到body,委托给元素匹配.clicked
  5. 事件通过 dom 冒泡到 body
  6. 在 body 上触发 click 事件处理程序
  7. .clickedjQuery 的 click 事件处理程序查找与选择器匹配的当前元素(主体)的后代的任何元素
  8. 它找到.wrap具有clicked类的 div 并调用该元素上的事件处理程序。
于 2013-08-19T18:29:25.543 回答