【问题标题】:Change element ID, but jQuery still fires event calling old ID. Why does this work?更改元素 ID,但 jQuery 仍会触发调用旧 ID 的事件。为什么这行得通?
【发布时间】:2015-09-10 23:27:08
【问题描述】:

我创建了一个小提琴来尝试调试我遇到的问题,一旦我使用 jQuery 重新排列 html 元素,这些元素上的悬停事件就不再起作用了。

但是,我在这里遇到了这个有趣的情况:http://jsfiddle.net/4yv1trj4/

我有一个主要的div,一旦我将鼠标悬停在它上面就会改变颜色。

$("#block").hover(function() {
     $(this).css("backgroundColor", "red");
}, function() {
    $(this).css("backgroundColor", "#888");        
});

如果你点击按钮,主div的ID会变成block2

$("#block").attr("id","block2");

但是当我将鼠标悬停在#block2 上时,$("#block").hover() 仍然会触发。此外,#block2 上的所有悬停调用都不起作用。 jQuery 的工作原理是否可以解释这一点?

【问题讨论】:

    标签: jquery jquery-hover


    【解决方案1】:

    当你这样做时:

    $("#block").hover(function() {
        $(this).css("backgroundColor", "red");
    }, function() {
        $(this).css("backgroundColor", "#888");        
    });
    

    您告诉 jQuery 查找 ID 为 block 的元素并将悬停事件绑定到它。完成此操作后,事件将保持绑定到该元素,无论其 ID 之后发生什么变化。

    也就是说,除非你有一些unbinds它的代码,当然。

    【讨论】:

    • 谢谢,这有助于我理解它。 jsfiddle.net/4yv1trj4/5 我将 jsfiddle 更新为 unbind 和 re?-bind,但代码看起来很难看,我不禁觉得可能有更好的方法来做到这一点。你认为 technophobia 的答案是精简我的代码的更好选择吗?
    • 我喜欢技术恐惧症的解决方法,但由于佳能 (stackoverflow.com/questions/31032004/…) 所述的问题,我不建议将其用于您的用例。我认为您的解决方案还不错。
    • 很明显,你必须面对一个交易——我个人在无数项目中使用.on()容器绑定,对性能的影响最小。
    • 'trade of' 的意思是'trade-off'
    【解决方案2】:

    作为 lucasnadalutti 回答的扩展:值得注意的是,您可以将绑定添加到容器并产生您期望的结果:

    例子:

    $("body").on("mouseenter", "#block", function () {
        $(this).css("backgroundColor", "red");
    }).on('mouseleave', "#block", function () {
        $(this).css("backgroundColor", "#888");
    });
    

    注意body 上的绑定,而不是实际元素。放在后兜里的小窍门。

    演示: jsFiddle


    更新:

    从评论部分,很明显需要一个警告 - 您应该绑定到页面上最近的元素。 body 在这里作为一个简单的例子。

    虽然我认为这个解决方案非常适合你,但在开始滥用这种权力之前,你应该阅读 Should all jquery events be bound to $(document)?

    【讨论】:

    • 有趣,我从来不知道这是一个选项。如果我用这个替换我的所有 click() 和 hover() 事件,这样做的任何部分是否被认为是不好的做法,考虑到如果我要这样做,我必须在我的代码中添加很多绑定和取消绑定路线?谢谢!
    • @Matt 是的,有问题。这实质上意味着您的事件必须通过 DOM 一直冒泡到 body 才能被处理。如果沿途有任何东西阻止传播,那你就有麻烦了。通常,此模式保留用于动态内容或避免附加大量处理程序,即:一个用于列表中的每个列表项。无论如何,如果您使用event delegation,您将始终希望选择最近的可靠祖先,而不是简单地使用body
    • 在小页面上进行测试,这些结果可能会很好;但是,随着页面的增长,附加到您的正文标签的每个事件(或使用佳能推荐附加的任何事件)将占用越来越多的资源。所以……为了以后的扩展,你可能想使用 lucasnadalutti 的建议直接使用标签,并根据需要解绑(当然除非你知道相关标签的内容会保持相对较小)
    • @Matt 我会绑定到最近的容器——性能对于大多数用例来说是完全可以接受的。但是,我仍然强烈建议您阅读我在答案底部发布的链接。祝你好运。
    • 感谢您添加该链接。我认为它帮助我更好地理解了一点。如果你不介意放纵我,为什么这个委派的例子不起作用? jsfiddle.net/4yv1trj4/8 在这种情况下,将变量作为选择器传递最终将成为解决我当前问题的最简单方法(根据用户输入在页面周围重新排列大量 HTML 内容),但似乎当该变量发生变化时,该函数不会为该选择器执行。谢谢!
    【解决方案3】:

    如果您删除 jQuery 悬停侦听器并添加 CSS 悬停,它会按照您想要的方式工作:

    #block:hover {
        background-color:red;
        width:300px;
        height:300px;
    }
    

    【讨论】:

    • 这个。不需要使用 jQuery 来完成这样的任务
    【解决方案4】:

    $("#block") 正在寻找特定的 DOM 对象。 .hover() 会将悬停事件绑定到该 DOM 对象。 $("#block").attr("id","block2"); 将更改该 DOM 对象的属性(id),但悬停事件仍然绑定到它。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-09-08
      • 1970-01-01
      • 2010-09-25
      • 2014-03-07
      • 1970-01-01
      相关资源
      最近更新 更多