【问题标题】:jQuery unbind event handler does not workjQuery unbind 事件处理程序不起作用
【发布时间】:2018-04-25 20:02:57
【问题描述】:

我正在动态地将节点(div)添加到 DOM 树并通过 jQuery(委托或非委托)附加事件侦听器。问题是我无法解开这些听众,结果他们堆积起来。这是一个示例代码,我找不到任何错误:

$(function() {
  var theTXT = '<div data-abc="tester">click here</div>';
  $("#loader").on('click', doClick);
  function doClick() {
    $("body").append(theTXT);
    $('[data-abc="tester"]').off('click', redoClick);
    $('[data-abc="tester"]').on('click', redoClick);
    function redoClick() {
      console.log("hi");
    }
  }
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="loader">load</div>

现在,如果我将 redoClick() 处理程序移到 doClick() 处理程序之外,一切正常。 任何帮助将不胜感激,这样我就可以理解为什么 .off() 不起作用。

【问题讨论】:

  • 为什么要在另一个函数中声明一个函数? oO
  • 目标是什么?对于每个添加的“单击此处”div,仅在第一次单击时记录“hi”?
  • @ZivWeissman 我更喜欢限制变量和函数的范围,这就是为什么
  • 我可以删除所有点击监听器,像这样: $('[data-abc="tester"]').off('click');但我宁愿避免这种粗暴的解决方案。
  • @j08691 不,问题以一种相当复杂的形式出现,其中一部分是动态创建的。这是 .off() 有问题的行为的过度简化版本。我不明白的是 on() 看到 redoClick() 处理程序并注册事件,而 off() 没有(!)。

标签: jquery events event-handling


【解决方案1】:

问题不在于“关闭”,问题在于事件处理程序。

因为你是在函数内部定义的,所以函数调用结束后会“超出范围”,所以 off 不能关闭这个特定的处理程序。

如果你把它放在它按计划工作的功能之外,另一个选择是删除它:

$(function() {
  var theTXT = '<div data-abc="tester">click here</div>';
  $("#loader").on('click', doClick);
  function doClick() {
    $("body").append(theTXT);
    $('[data-abc="tester"]').off('click'); //remove the handler
    $('[data-abc="tester"]').on('click', redoClick);
    function redoClick() {
      console.log("hi");
    }
  }
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="loader">load</div>

现在,如果我将 redoClick() 处理程序移到 doClick() 处理程序之外, 一切正常。

因为它是在函数外部声明的,所以 .off 可以访问它。

但这是我的问题:on() 是如何工作的?我在这里错过了什么?

第一次单击时,您将有一个处理程序,比如说 doClick#1,首先“off”将尝试删除 doClick#1(未绑定)-然后 on 将单击,绑定 doClick#1。第二次运行时,您将创建 doClick#2,再次关闭将尝试删除 doClick#2 - 未找到,而 on 将添加 doClick#2(因此您将拥有 #1+#2 等等)

【讨论】:

  • 谢谢。我已经尝试过这些解决方案,并确认它们有效。但这是我的问题: on() 是如何工作的?我在这里错过了什么?
  • 因为您在定义“doClick”的同一范围内声明“on”,而“off”将在下次您的函数创建另一个“doClick”实例时打开@ ThomasMavrofides - 编辑了我的答案,希望它更清楚
  • 现在明白了,谢谢,我认为你是对的。感谢您的宝贵时间。
  • 很高兴为您提供帮助。只是不要忘记标记为答案,谢谢。
【解决方案2】:

好吧,傻瓜,具体问题的答案(即如何不将事件侦听器重新附加到一堆元素)非常简单。今天早上它击中了我。而不是使用

$('[data-abc="tester"]').on('click', redoClick);

我应该使用:

$('[data-abc="tester"]').last().on('click', redoClick);

做到了,不需要 off()

【讨论】:

    猜你喜欢
    • 2010-09-12
    • 2012-01-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-11-12
    • 1970-01-01
    • 2018-09-22
    相关资源
    最近更新 更多