【问题标题】:Why isn't a handler on the same element run after stopPropagation为什么在 stopPropagation 之后不在同一元素上运行处理程序
【发布时间】:2013-06-05 11:17:24
【问题描述】:

对于http://jsfiddle.net/mgs_jsfiddle/HXMCs/,如果鼠标移到子区域,为什么不运行第一个事件处理程序?

<div class="top">
    <div class="sub"></div>
</div>

$(".top").bind("mouseover mouseout", function(e) {
});

$(".top").on("mouseover mouseout", ".sub", function(e) {
    e.stopPropagation();
});

两个处理程序都附加到顶部元素。 stopPropagation 的文档告诉我“这不会阻止同一元素上的其他处理程序运行”。那么不应该调用第一个处理程序吗?

【问题讨论】:

  • 你为什么要混合 bind 和 on?当你没有按照你应该的方式使用它们时,你不能指望事情会按照他们声称的方式工作。您正在侦听不同元素上的事件,而您恰好将侦听器附加在同一位置。
  • 混合?因为它在真实代码中是有意义的。在顶部下方的深层层次中有许多子。并且 top 还必须监听事件,因为 top 没有完全被 subs 覆盖。
  • 虽然您将事件委托给.top,但它会监听.sub 上的事件。 jQuery 足够聪明,可以像处理一次正常的委托事件一样处理委托事件。
  • 阅读文档后我不会这么认为。它说“委托事件方法仅将事件处理程序附加到一个元素”。此外,如果 jQuery 监听了 subs,它怎么知道后来创建的 subs?

标签: jquery events stoppropagation


【解决方案1】:

这两个事件:

$(".top").bind("mouseover mouseout", function(e) {
});

$(".top").on("mouseover mouseout", ".sub", function(e) {
    e.stopPropagation();
});

附加到.top。但第二个是委托事件,jQuery 模拟它就像它是一个普通事件一样。如果你删除stopPropagation:

$(".top").bind("mouseover mouseout", function(e) {
});

$(".top").on("mouseover mouseout", ".sub", function(e) {
});

您会注意到第二个事件首先被触发,就好像它直接附加到.sub。 jQuery 模拟委托事件的传播,就好像它是一个普通事件一样。

显然,如果子元素停止传播,则父元素将不会收到该事件。但正如我提到的,它只是 jQuery 中的一个模拟。

更新

虽然 jQuery 官网在http://api.jquery.com/on/ 上解释得很好,但我还是会尝试简单解释一下on 方法。

on 方法是在 jQuery 1.7 中引入的。它被认为可以替代之前用于绑定事件的几种方法:binddelegatelive。最后两个用于附加委托事件。现在您可以使用单一方法 on 附加它们。

常规活动

$(".top").on("mouseover mouseout", function(e) {

});

完全一样
$(".top").bind("mouseover mouseout", function(e) {

});

委托活动

$(".top").on("mouseover mouseout", ".sub", function(e) {

});

一样
$(".top").delegate(".sub", "mouseover mouseout", function(e) {

});

委托事件有什么用途?

  • 如果您的 html 是动态更改的。例如。你有一个&lt;table&gt; 并且你在表行上绑定了一些事件:

    $("table tr").on("click", function(e) {
    
    });
    

    此事件不会在动态插入的行上触发。一种解决方法是使用委托事件:

    $("table").on("click", "tr", function(e) {
    
    });
    

    事件附加到表而不是行。所以它可以处理以后插入的任何行。

  • 如果您有大量类似的元素。在这种情况下,如果您直接在元素上绑定事件,它可能会降低您的应用程序的速度。至少在 IE 中:) 所以使用委托事件可能会显着提高性能。你可以从第一点看例子。

委托事件如何工作?

我们以&lt;table&gt;为例:

    $("table").on("click", "tr", function(e) {

    });

我们将事件附在桌子上,但要求它检查事件是否在 tr 发起。

上面示例的粗略实现可能如下所示:

    $("table").on("click", function(e) {
        var tr = $(e.target).parentsUntil(this, 'tr');
        if (tr.length){
            //the event was triggered on tr inside table
            //do some stuff
        }
    });

【讨论】:

  • 那么这个测试jsfiddle.net/mgs_jsfiddle/sdNes呢,在顶层和底层之间放置了另一层?如果鼠标移动到灰色区域,调用mid-handler可以吗?如果两个祖先都被调用或都不被调用,那将是一致的?
  • 你是对的,它会是一致的。但正如我所说,jQuery 只是模仿它。并且它不能在直接事件之前触发委托事件。第一个直接事件被触发,然后事件在 DOM 中冒泡并被.top 捕获。然后 jQuery 尝试找到 .sub 元素并对其执行回调。
  • 因此,重要的是要理解为祖先编写“on”与为满足选择器的每个元素编写“bind”不同。
  • 其实bind 已经过时了。在这两种情况下,您都应该使用on。唯一的区别在于第二个参数。如果它是一个选择器字符串,那么 jQuery 会将其视为一个委托事件。
  • 已过时?在了解了今天的小提琴之后,我认为on 关于stopPropagation 有点奇怪。在需要时使用bind 是有原因的。
猜你喜欢
  • 2011-02-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-10-19
相关资源
最近更新 更多