【问题标题】:stopPropagation and live() method. What am I missing?stopPropagation 和 live() 方法。我错过了什么?
【发布时间】:2012-12-19 09:53:00
【问题描述】:

我已经阅读了 jQuery 文档,并且我知道如果我使用 live() 将事件绑定到元素,那么使用 stopPropagation() 是没有意义的,因为带有 live() 的事件会绑定到文档节点,所以事件已经发生了向上。这么说,我认为 nex 代码会发出 3 次警报,因为 stopPropagation 不会停止任何事情:

<ul style="border:red solid 1px;">
    <li style="padding:10px; border:blue solid 1px;">
        <p style="border:green solid 1px;"><a href="#">link</a></p>
    </li>
    <li style="padding:10px; border:blue solid 1px;">
        <p style="border:green solid 1px;">no link</p>
    </li>
</ul>

<script type="text/javascript">
    $('a').live( "click", function( e ) {alert("link");e.stopPropagation()} );
    $('ul').live( "click", function( e ) {alert("ul");} );
    $('ul li').live( "click", function( e ) {alert("li");} );
</script>

当我单击链接时,我期望并警告“li”和“ul”,但是 stopPropagation 正在停止其他本应无用的事件。 我错过了什么?

【问题讨论】:

  • 为什么不只是$('a').on( "click", function() {alert("link"); return false;} );
  • 如果我单击确切的链接,您的代码将按预期工作。我没有看到 ul 和 li 警报。如果我点击实际链接旁边的空间,我会看到另外两个警报。您可能希望为元素设置宽度,以免看到此行为。
  • 似乎是因为对于 ul 和 ul li,您还使用了 live。如果您将它们更改为bind,它们都会被调用。

标签: events jquery stoppropagation


【解决方案1】:

根据documentation stopPropagation()live() 中无法正常工作,因为live() 仅在事件已经冒泡到document 之后才执行。

但是,如果您使用的是 jQuery 1.4.3 或更高版本,stopPropagation() 开始工作了。

live() 自 1.4.3 以来被多次重写。
live() 文档列出了许多首选使用其他绑定方法的原因。尽管文档中的信息似乎是指 1.4.1 的行为,并且似乎与当前的实际行为没有 100% 同步。

例如查看添加了on() 的1.7.1 源,它显示live() 正在使用on()

live: function( types, data, fn ) {
    jQuery( this.context ).on( types, this.selector, data, fn );
    return this;
}

DEMO - 使用您的代码并使用 jQuery 1.4.1 - stopPropagation 无法正常工作

DEMO - 使用您的代码并使用 jQuery 1.4.3 - stopPropagation 现在可以工作了

总结

live() 在 1.4.3 中被重写。我认为是因为 delegate() 已被添加。
live() 随着改进的添加,随着每个版本的 jQuery 不断更新。

一般来说,为了防止live() 出现任何令人惊讶的结果,最好遵循documentation 的指导方针,并针对给定版本的 jQuery 使用建议的方法:

$(selector).live(events, data, handler);                // jQuery 1.3+
$(document).delegate(selector, events, data, handler);  // jQuery 1.4.3+
$(document).on(events, selector, data, handler);        // jQuery 1.7+

为了完整起见,我在下面添加了 1.4.1 和 1.4.3 的 live() 源提取。

1.4.1 源码

live: {
    add: function(proxy, data, namespaces, live) {
        jQuery.extend(proxy, data || {});

        proxy.guid += data.selector + data.live;
        data.liveProxy = proxy;

        jQuery.event.add(this, data.live, liveHandler, data);

    },

    remove: function(namespaces) {
        if (namespaces.length) {
            var remove = 0,
                name = new RegExp("(^|\\.)" + namespaces[0] + "(\\.|$)");

            jQuery.each((jQuery.data(this, "events").live || {}), function() {
                if (name.test(this.type)) {
                    remove++;
                }
            });

            if (remove < 1) {
                jQuery.event.remove(this, namespaces[0], liveHandler);
            }
        }
    },
    special: {}
}

1.4.3 源码

live: {
    add: function(handleObj) {
        jQuery.event.add(this, liveConvert(handleObj.origType, handleObj.selector), jQuery.extend({}, handleObj, {
            handler: liveHandler,
            guid: handleObj.handler.guid
        }));
    },

    remove: function(handleObj) {
        jQuery.event.remove(this, liveConvert(handleObj.origType, handleObj.selector), handleObj);
    }
}

【讨论】:

  • 它是not working in 1.4.3,无论如何我投了反对票,因为你90%的帖子被误导了live与委托有某种不同
  • @Esailija:我添加了演示,显示它在 1.4.1 中工作,并评论了 1.4.3 中的更改。在 1.4.3 中,live() 被重写,很可能是因为当时添加了 delegate()live() 是在 1.4.1 中添加的,其中 stopPropagation() 没有按预期工作。在 1.4.3 中添加了 delegate() 以取代 live()。我认为这就是为什么 jQuery live() 在每个版本中都被重写的原因,如果有改进的话。为了方便起见,我还在 1.4.1 和 1.4.3 中添加了 live 的源代码。
  • 这种行为还是很奇怪和不直观,它们都绑定到document并且只在document上处理,只有e.stopImmediatePropagation应该有效果。例如,这应该是等价的,但事实并非如此。 jsfiddle.net/PHvVh
  • @Esailija:我完全同意。它很奇怪。我在 live() 的文档中也找不到任何关于整个版本中 live 变化的内容,这使得文档中提出的一些关于 live() 不起作用的要点变得多余和混乱。
  • 感谢所有回复。我以为我可能会遗漏一些东西,但事实证明这取决于 jquery ver。相同的方法效果不同。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-07-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多