【问题标题】:Click event handler inadvertently bubbles, even after calling jQuery's stopPropagation()即使在调用 jQuery 的 stopPropagation() 之后,单击事件处理程序也会无意中冒泡
【发布时间】:2010-06-25 02:16:10
【问题描述】:

我正在尝试为列表中“li”元素中的不同元素设置不同的委托单击处理程序。示例:

<ul id='myList'>
  <li>
    <p>First item.</p>
    <button>button1</button>
    <button>button2</button>
  </li>
  <li>
    <p>Second item.</p>
    <button>button1</button>
    <button>button2</button>
  </li>
</ul>

当用户单击 button1(任何项目)时,我想抓取该事件并停止传播(对于 button2 实例也是如此)。单击父 li 元素的用户将是不同的处理程序:

$('#myList').delegate('li', 'click', function() {
    alert("You clicked a parent <li> item!");
});

$('#myList').delegate('button', 'click', function(event) {
    event.stopPropagation();
    event.stopImmediatePropagation();
    alert("You clicked a button (but which one?)!");
});

所以一个问题是,我如何为 button1 实例设置一个委托,而为 button2 实例设置另一个委托?上例中的第二个委托在单击按钮时会触发,但 event.stopPropagation() 似乎无法正常工作,因为仍会调用父 li 项的处理程序,

------更新--------------

也尝试调用 event.stopImmediatePropagation(),但没有效果,父处理程序仍然被调用。

谢谢

【问题讨论】:

  • 你用哪个浏览器测试过这个?
  • @user - 仅供参考,.stopPropagation() 不起作用的原因是 delegate() 依赖 冒泡工作。换句话说,您将处理程序放置在#myList 上,因此当您单击其后代之一时,事件会冒泡到#myList,然后触发。所以没有更多的传播可以停止。

标签: javascript jquery event-bubbling


【解决方案1】:

也许在父母中:

$('#myList').delegate('li', 'click', function(event) {
    if (!$(event.target).is('button')) {
        alert("You clicked a parent <li> item!");
    }
});

【讨论】:

  • 好的,因为模型工作,我为每个按钮类型设置了一个不同的类,然后在这个父处理程序中检查目标类型/类,谢谢。
  • 对我来说似乎是 jQuery 中的一个错误,因为这就是委托应该做的 - 将事件目标与选择器匹配。看起来是这样 - jsfiddle.net/SxsbK
【解决方案2】:

确实,它应该可以工作,我尝试单步执行 jQuery 代码,但无济于事。相反,我做了这个:

(function(){
  var el = document.getElementsByTagName("li");
  var i = el.length;

  while (i--)
    el[i].onclick = function () {
      alert("You clicked a parent <li> item!");
    };

  el = document.getElementsByTagName("button");
  i = el.length;

  while (i--)
    el[i].onclick = function (event) {
      var e = event || window.event;

      e.stopPropagation();
      e.cancelBubble = true;
      alert("You clicked a button (but which one?)!");
    };

})();

按照您希望的方式工作(但未在 IE 中测试)。现在,也许明天,我已经厌倦了进一步研究这个问题。

回答您的其他问题:我认为您确实应该将ids 或classes 添加到您的&lt;button&gt;s 中,这样您就可以轻松测试调用了哪个按钮。

【讨论】:

    【解决方案3】:

    你可以试试event.stopImmediatePropagation()。从理论上讲,您所拥有的应该可以工作,因此扩展它可能会有所帮助。

    【讨论】:

    • 是的,运气不好,尝试添加它,但仍会调用父处理程序。
    【解决方案4】:

    原因是.delegate() 只会在单击事件通过子元素向下传递到 myList 时执行单击函数。然后它将执行每个匹配的委托,因此它在您的示例中正确调用两者,因为当点击到达 myList 时,它已经通过了 BUTTON 和 LI。

    由于您在 BUTTON 之前绑定了 LI,因此 LI 代表在被调用的列表中是第一个,您可以先绑定 BUTTON ,它应该可以工作。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-02-13
      • 2011-10-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多