【问题标题】:How to check if click event is already bound - JQuery如何检查单击事件是否已绑定 - JQuery
【发布时间】:2011-09-15 17:31:19
【问题描述】:

我正在用一个按钮绑定一个点击事件:

$('#myButton').bind('click',  onButtonClicked);

在一种情况下,这会被多次调用,所以当我执行 trigger 时,我看到了多个我想要阻止的 ajax 调用。

我如何bind 之前没有绑定。

【问题讨论】:

  • 伙计,我认为 +Konrad Garus 拥有最安全的答案 (stackoverflow.com/a/6930078/842768),请考虑更改您接受的答案。干杯!更新:也检查 +Herbert Peters 的评论!这是最好的方法。
  • 对于当前标准,请参阅下面的@A Morel 的回答 (stackoverflow.com/a/50097988/1163705)。编码更少,无需进行所有猜测工作、算法和/或搜索现有元素。

标签: jquery


【解决方案1】:

另一种方法 - 使用 CSS 类和过滤器标记此类按钮:

$('#myButton:not(.bound)').addClass('bound').bind('click',  onButtonClicked);

在最近的 jQuery 版本中,将 bind 替换为 on

$('#myButton:not(.bound)').addClass('bound').on('click',  onButtonClicked);

【讨论】:

  • 太棒了!谢谢康拉德,这达到了最佳效果。我喜欢这样优雅而简单的方法。我很确定它的性能也更高,因为每个元素(已经附加了点击事件处理程序)不必在比较每个大事件桶中进行完整搜索。在我的实现中,我将添加的辅助类命名为“click-bound”,我认为这是一个更易于维护的选项:$(".list-item:not(.click-bound)").addClass("click-bound") ;
  • 正如接受的答案中所述:“当然,如果您可以构建您的应用程序以便此代码只被调用一次,那将是最好的。”这样就完成了。
  • +1 在我的情况下,关闭/打开和绑定/取消绑定确实阻止了多次调用。这是行之有效的解决方案。
  • 这是更好的性能解决方案,因为代码可以检查 CSS 类的存在和已经存在的滑动绑定。其他解决方案执行一个 unbind-then-rebind 过程,但开销更大(至少我可以说是这样)。
  • 2 个问题。 (在可以绑定到多个元素的插件中使用它时)将调整大小事件绑定到窗口对象时将不起作用。使用 data( 'bound', 1 ) 而不是 addClass ('bound') 是另一种可行的方法。在销毁事件时,它可能会这样做,而其他实例则依赖于它。因此,建议检查其他实例是否仍在使用中。
【解决方案2】:

2012 年 8 月 24 日更新:在 jQuery 1.8 中,不再可能使用 .data('events') 访问元素的事件。 (有关详细信息,请参阅this bug。)可以使用内部数据结构jQuery._data(elem, 'events') 访问相同的数据,该结构未记录在案,因此不能 100% 保证保持稳定。不过这应该不是问题,上面插件代码的相关行可以改成如下:

var data = jQuery._data(this[0], 'events')[type];

jQuery 事件存储在一个名为 events 的数据对象中,因此您可以在此搜索:

var button = $('#myButton');
if (-1 !== $.inArray(onButtonClicked, button.data('events').click)) {
    button.click(onButtonClicked);
}

当然,如果您可以构建您的应用程序,这样该代码只被调用一次,那将是最好的。


这可以封装到插件中:

$.fn.isBound = function(type, fn) {
    var data = this.data('events')[type];

    if (data === undefined || data.length === 0) {
        return false;
    }

    return (-1 !== $.inArray(fn, data));
};

然后你可以调用:

var button = $('#myButton');
if (!button.isBound('click', onButtonClicked)) {
    button.click(onButtonClicked);
}

【讨论】:

  • +1 表示编辑。今天阅读这篇文章,我正在使用 1.8。谢谢。
  • 感谢编辑。这仅用于按钮还是我也可以将它用于<a>?因为当我尝试时它在jQuery._data() 上显示以下错误TypeError: a is undefined
  • 我会将var data = jQuery._data(this[0], 'events')[type]; 行换成try catch 并在catch 中返回false。如果没有事件绑定到 this[0],那么对 [type] 的调用将导致“无法获取未定义或空引用的属性‘点击’”的一些变化,显然这也告诉你你需要知道什么。跨度>
  • 我不确定 jQuery 2.0.3 中的 _data 对象是否发生了变化,但我不能为此使用 $.inArray。您要比较的函数位于每个数据项的属性中,称为“处理程序”。我修改它以使用一个简单的 for 语句并检查字符串等价性,我假设 inArray 做了什么。 for (var i = 0; i < data.length; i++) { if (data[i].handler.toString() === fn.toString()) { return true; } }
  • 为什么不将您的更新/编辑移到顶部?...这是实际正确的答案。
【解决方案3】:

如果使用 jQuery 1.7+:

您可以在on之前拨打off

$('#myButton').off('click', onButtonClicked) // remove handler
              .on('click', onButtonClicked); // add handler

如果没有:

你可以在第一个事件中解绑它:

$('#myButton').unbind('click', onButtonClicked) //remove handler
              .bind('click', onButtonClicked);  //add handler

【讨论】:

  • 这不是一个很好的解决方案,但只需解除绑定一个处理程序即可改进:.unbind('click', onButtonClicked)See the manual
  • 您实际上可以在添加处理程序时为其命名,然后解除绑定变得非常简单。 $(sel).unbind("click.myNamespace");
  • @lonesomeday 是您使用“unbind”的示例,是为了展示不同的东西吗? .unbind 与 .off 不一样吗,所以你必须写 $('#myButton').unbind('click', onButtonClicked).bind('click', onButtonClicked);
  • @Jim 你会看到问题在我发表评论三年后被编辑! (也是在我发表评论后的几分钟内。我评论的内容不再存在,这就是为什么它似乎没有多大意义。)
  • @lonesomeday 嗯我不知道为什么要编辑它,你认为我应该回滚吗?
【解决方案4】:

我看到的最好方法是使用 live() 或 delegate() 在父元素中而不是在每个子元素中捕获事件。

如果您的按钮位于#parent 元素内,您可以替换:

$('#myButton').bind('click', onButtonClicked);

通过

$('#parent').delegate('#myButton', 'click', onButtonClicked);

即使在执行此代码时#myButton 还不存在。

【讨论】:

  • 不推荐使用的方法
【解决方案5】:

我写了一个非常小的插件,叫做“once”。在元素中执行关闭和开启。

$.fn.once = function(a, b) {
    return this.each(function() {
        $(this).off(a).on(a,b);
    });
};

简单地说:

$(element).once('click', function(){
});

【讨论】:

  • .one() 将在第一次执行后删除处理程序。
  • 这里的“once”用于附加处理程序一次。 jquery中的“one”是运行一次而不是附加一次。
  • 我知道我是在事后介入的,但off 不会删除给定类型的所有处理程序吗?这意味着如果有一个单独的点击处理程序不相关但在同一个项目上,那不会也被删除吗?
  • 只需在事件上使用命名空间,这样它就不会删除所有处理程序,例如:'keypup.test123'
【解决方案6】:

为什么不用这个

unbind()bind() 之前

$('#myButton').unbind().bind('click',  onButtonClicked);

【讨论】:

  • $('#myButton').off().on('click', onButtonClicked); 也适用于我。
  • 为我工作...gr8 解决方案
  • 美丽。对我来说非常适合已经绑定的按钮。
【解决方案7】:

这是我的版本:

Utils.eventBoundToFunction = function (element, eventType, fCallback) {
    if (!element || !element.data('events') || !element.data('events')[eventType] || !fCallback) {
        return false;
    }

    for (runner in element.data('events')[eventType]) {
        if (element.data('events')[eventType][runner].handler == fCallback) {
            return true;
        }

    }

    return false;
};

用法:

Utils.eventBoundToFunction(okButton, 'click', handleOkButtonFunction)

【讨论】:

    【解决方案8】:

    为避免检查/绑定/取消绑定,您可以更改方法! 为什么不使用 Jquery .on() ?

    由于 Jquery 1.7,.live(), .delegate() 已被弃用,现在您可以使用 .on() 来

    为匹配当前选择器的所有元素附加一个事件处理程序,现在和将来

    这意味着您可以将事件附加到仍然存在的父元素并附加子元素,无论它们是否存在!

    当你像这样使用 .on() 时:

    $('#Parent').on('click', '#myButton'  onButtonClicked);
    

    您在父项上捕获事件单击并搜索子项“#myButton”(如果存在)...

    所以当你删除或添加子元素时,你不必担心是添加还是删除事件绑定。

    【讨论】:

    • 这绝对是当前标准的最佳答案。我不认为将处理程序设置在父母身上以监视孩子的这一功能已经得到很好的宣传,但它是一个相当优雅的解决方案。我多次触发事件,并且每次触发的总次数都在不断增加。这一行就完成了整个技巧,并且没有使用.off,我相信这会删除过程中不相关的处理程序。
    【解决方案9】:

    基于@konrad-garus 的回答,但使用data,因为我认为class 应该主要用于造型。

    if (!el.data("bound")) {
      el.data("bound", true);
      el.on("event", function(e) { ... });
    }
    

    【讨论】:

      【解决方案10】:

      试试:

      if (typeof($("#myButton").click) != "function") 
      {
         $("#myButton").click(onButtonClicked);
      }
      

      【讨论】:

        【解决方案11】:
        if ($("#btn").data('events') != undefined && $("#btn").data('events').click != undefined) {
            //do nothing as the click event is already there
        } else {
            $("#btn").click(function (e) {
                alert('test');
            });
        }
        

        【讨论】:

          【解决方案12】:

          截至 2019 年 6 月,我已经更新了该功能(它可以满足我的需要)

          $.fn.isBound = function (type) {
              var data = $._data($(this)[0], 'events');
          
              if (data[type] === undefined || data.length === 0) {
                  return false;
              }
              return true;
          };
          

          【讨论】:

            【解决方案13】:

            JQuery 有solution:

            $( "#foo" ).one( "click", function() {
              alert( "This will be displayed only once." );
            }); 
            

            等效:

            $( "#foo" ).on( "click", function( event ) {
              alert( "This will be displayed only once." );
              $( this ).off( event );
            });
            

            【讨论】:

            • 您的回答与问题无关。问题是关于绑定函数到元素的事件只有一次。
            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2014-04-07
            • 1970-01-01
            • 1970-01-01
            • 2011-11-12
            • 1970-01-01
            • 2013-07-31
            • 2015-01-14
            相关资源
            最近更新 更多