【问题标题】:How can I temporarily disable click events on a button without actually disabling it?如何在不实际禁用按钮的情况下暂时禁用按钮上的点击事件?
【发布时间】:2020-12-18 17:31:53
【问题描述】:

使用 jQuery,我想在不更改给定按钮的 disabled 属性的情况下禁用它的所有点击事件。

我正在考虑检索单击事件处理程序,取消绑定并存储它们(例如,使用data())。

然后我可以在按钮再次启用后重新绑定它们。

【问题讨论】:

  • 您可能需要重新考虑您的方法 - 如果您希望按钮不起作用,请禁用它。这清楚地向用户表明该按钮已禁用。它比解决默认行为更整洁、更简单、更一致。为什么要避免禁用该按钮?

标签: javascript jquery


【解决方案1】:

这并不难,因为 jQuery 已经将其所有事件处理程序存储为元素本身的data()。你可以通过.data().events获取(和修改)这个对象。

现在您可以使用以下方法轻松保存对处理程序的引用:

 events._click = events.click;
 events.click = null;

然后使用以下方法恢复它们:

 events.click = events._click;
 events._click = null;

请注意,这不会禁用通过.delegate().live() 绑定的事件,因为它们通过事件冒泡/传播起作用。要同时禁用这些,只需绑定一个阻止传播到祖先元素的新处理程序:

 events._click = events.click;
 events.click = null;
 // Block .live() and .delegate()
 $("#el").click(function (e) {
     e.stopPropagation();
 });

当需要再次启用处理程序时,您甚至不需要取消绑定此阻止函数,因为events.click = events._click 将覆盖您刚刚与所有旧处理程序绑定的函数。

【讨论】:

  • 这种方法可能会有问题。一方面,我想我在某处读到,新版本的 jQuery 不支持这种行为。但即使这不是真的,它也不是记录在案的行为,所以我不能依赖它来开发 jQuery 的未来版本。
  • @Ovesh,顺便说一句,我认为 Javascript 是其中一种语言,可能是由于它的动态特性、事实上的“开源”(从未编译过,只是有时会缩小)和历史浏览器不兼容性,隐藏/保护实现细节的兴趣较少。只要了解风险,并且不存在更好的替代方案,那么就可以随意潜入、修改原型、覆盖函数,一般来说......破解;)
  • 同意。我会接受答案,因为可能没有更好的解决方案。
  • 这似乎不再起作用(至少从 jQuery 1.10 开始)。
【解决方案2】:

这是另一种方式:

$("#myButton").click(function() {
    if ($(this).attr("temp_disable") == "disabled") {
        //nothing to do, temporarily disabled...
    }
    else {
        alert("You clicked me!");
    }
});

要“禁用”它 10 秒:

$("#myButton").attr("temp_disable", "disabled");
window.setTimeout(function() { $("#myButton").attr("temp_disable", ""); }, 10000);

现场测试用例:http://jsfiddle.net/yahavbr/ByM6h/

【讨论】:

  • 这就是我最终做的事情。但问题是,它必须添加到定义的每个处理程序中。从设计的角度来看,这不是一个好的解决方案,因为某些事件可能是由不受我控制的代码添加的。
  • @Ovesh 除了真正禁用按钮之外,“全局”执行此操作的唯一方法是将其更改为其他内容,例如div 只是看起来像一个按钮,然后在时间到期时将其更改回按钮 - 希望事件处理程序将被保留,需要先检查它。
  • 这其实是个好主意。您可以将其替换为启用样式的按钮(不附加点击事件),并使用data() 保留原始按钮。然后把原来的按钮换回去。
【解决方案3】:

这就是要走的路。如果您将 onclick 指定为属性,则可以切换属性总线

 $(button_element).attr('click', '');

 $(button_element).attr('click', 'do_the_regular_action()');

【讨论】:

  • 假设我不知道分配给元素的所有事件处理程序。而且可能不止一个。
【解决方案4】:

这里的所有答案现在都已过时 - 从 jQuery 1.7 开始,您应该使用 .off() 解释 on the official jQuery site

<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <title>off demo</title>
  <style>
  button {
    margin: 5px;
  }
  button#theone {
    color: red;
    background: yellow;
  }
  </style>
  <script src="https://code.jquery.com/jquery-1.10.2.js"></script>
</head>
<body>
 
<button id="theone">Does nothing...</button>
<button id="bind">Add Click</button>
<button id="unbind">Remove Click</button>
<div style="display:none;">Click!</div>
 
<script>
function flash() {
  $( "div" ).show().fadeOut( "slow" );
}
$( "#bind" ).click(function() {
  $( "body" )
    .on( "click", "#theone", flash )
    .find( "#theone" )
      .text( "Can Click!" );
});
$( "#unbind" ).click(function() {
  $( "body" )
    .off( "click", "#theone", flash )
    .find( "#theone" )
      .text( "Does nothing..." );
});
</script>
 
</body>
</html>

【讨论】:

  • 我会接受这一点,但我希望首先编辑该示例以在不带参数的情况下调用 off(),以显示它如何删除所有附加事件(无需保留对它们的引用)。这将更密切地解决原始问题。
【解决方案5】:

您可以使用unbindbind

$('#control').unbind('click');

$('#control').bind('click', NameOfFunctionToCall);

【讨论】:

  • 我认为这不能回答 OP 的问题(尽管我可能是错的)。听上去,可能有多个点击处理程序,他可能无法获取到处理程序的引用进行绑定(例如匿名函数,或在另一个范围内的函数)。
【解决方案6】:

我将扩展 Barry 和 Thariama 提供的答案...我认为这将满足 Ovesh 的反对意见:

您可以将命名空间添加到您的事件绑定。这使您可以稍后引用该特定事件绑定,而不会与其他绑定发生冲突。我认为这比公认的答案更干净......(公平地说,在最初的问题出现时,jQuery 中可能没有这个功能)。

// A generic click handler:
$('.myButton').click(function() { ... });

// A namespaced click handler:
$('.myButton').bind('click.someSituation', function()  { ... });

// Later you can unbind only the handler you want by using the namespace:
$('.myButton').unbind('click.someSituation');

// The default click handler still works.

【讨论】:

  • 我想我应该在问题中说得更清楚。可能有多个点击事件,并非所有点击事件都受我的代码约束。这个解决方案不够通用。
  • 在我的示例中,通用 .click() 是一个由其他代码绑定的事件。命名空间 .bind(click...) 在您的代码中。您可以取消绑定您的命名空间点击处理程序,而不会影响其他点击处理程序。
  • 啊,但问题是,我想禁用它上面的 all 点击事件。
【解决方案7】:

而不是做这件事使用 Core Javascript 来做这个任务 例如看下面的例子。

function MakeSaveDisabled(flg) {
    if (flg != null) {
        $(".btnpost").each(function () {
            this.removeAttribute("disabled");
            if (this.hasAttribute("oclickevt")) {
                this.setAttribute("onclick", this.getAttribute("oclickevt"));
            }
        });
    }
    else {
        $(".btnpost").each(function () {
            this.setAttribute("disabled", "true");
            if (this.getAttribute("onclick") != null) {
                this.setAttribute("oclickevt", this.getAttribute("onclick"));
            }
            this.removeAttribute("onclick");
        });
    }
}

将javascript函数保存在某个临时属性中,并在需要时绑定它。

【讨论】:

    【解决方案8】:

    您可以保存事件然后恢复它们,这似乎可行(请注意,_ 可能需要根据 JQuery 的版本省略)。

    此示例停止引导切换更改事件触发,然后触发切换,然后将事件重置为之前的任何事件。你可以通过点击等来做同样的事情。

    var events;
    // Save change events associated with this control
    events = $._data($(this)[0], "events").change;
    $._data($(this)[0], "events").change = null;
    
    // Do your stuff here
    $(this).bootstrapToggle("off");
    
    // Reset change events
    $._data($(this)[0], "events").change = events;
    

    【讨论】:

      猜你喜欢
      • 2020-08-14
      • 1970-01-01
      • 2011-10-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多