禁用普通JavaScript和jQuery中的按钮

内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用

  • 回答 (2)
  • 关注 (0)
  • 查看 (56)

Vanilla JavaScript

可以使用以下语句轻松启用和禁用按钮:

button.disabled = state;

这适用于人类尝试点击按钮时以及以编程方式点击按钮时的情况:

var button = document.getElementById('myButton');

button.addEventListener('click', function() {
    alert('world');
});

button.disabled = true;
button.click(); // No output
button.disabled = false;
button.click(); // Output : "Hello" and "world
button.disabled = true;
button.click(); // No output

<input type="button" id="myButton" value="button" onClick="alert('Hello')"/>

这也适用于使用MouseEvent界面时:

var button = document.getElementById('myButton');

var click = new MouseEvent("click", {
    "view": window
});

button.addEventListener('click', function() {
    alert('world');
});

button.disabled = true;
button.dispatchEvent(click); // No output
button.disabled = false;
button.dispatchEvent(click); // Output : "Hello" and "world
button.disabled = true;
button.dispatchEvent(click); // No output

<input type="button" id="myButton" value="button" onClick="alert('Hello')"/>

jQuery的

但我似乎无法用jQuery做同样的事情:

var button = $("#myButton");

button.on("click", function() {
    alert("world");
});

button.prop("disabled", true);
button.click(); // Output : "world" and "Hello"
button.prop("disabled", false);
button.click(); // Output : "world" and "Hello"
button.prop("disabled", true);
button.click(); // Output : "world" and "Hello"

<script src="https://code.jquery.com/jquery-1.12.2.min.js"></script>
<input type="button" id="myButton" value="button" onClick="alert('Hello')"/>

button.prop("disabled", true);button.attr("disabled", true);简单地改变disabled按钮元素的属性,但没有禁用实际点击事件。这意味着button.click();即使按钮被禁用,每当被调用时都会触发事件!

此外,“wrold”和“hello”以错误的顺序输出。

我可以想出最简单的代码来模拟vanilla JavaScript版本的行为,这是:

var button = $("#myButton");

button.on("click", function() {
    alert("world");
});

button.disable = (function() {
    var onclick = null;
    var click = [];
    return function(state) {
        if(state) {
            this.prop('disabled', true);
            if(this.prop('onclick') !== null) {
                onclick = this.prop('onclick');
                this.prop('onclick', null);
            }
            var listeners = $._data(this.get()[0], "events");
            listeners = typeof listeners === 'undefined' ? [] : listeners['click'];
            if(listeners && listeners.length > 0) {
                for(var i = 0; i < listeners.length; i++) {
                    click.push(listeners[i].handler);
                }
                this.off('click');
            }
        } else {
            this.removeProp('disabled');
            if(onclick !== null) {
                this.prop('onclick', onclick);
                onclick = null;
            }
            if(click.length > 0) {
                this.off('click');
                for(var i = 0; i < click.length; i++) {
                    this.on("click", click[i]);
                }
                click = [];
            }
        }
    }
})();

button.disable(true);
button.click(); // No output
button.disable(false);
button.click(); // Output : "Hello" and "world
button.disable(true);
button.click(); // No output

<script src="https://code.jquery.com/jquery-1.12.2.min.js"></script>
<input type="button" id="myButton" value="button" onClick="alert('Hello')"/>

我的问题

  • 为什么jQuery(与vanilla JS不同)在禁用按钮时不会禁用事件?
  • 这是被视为jQuery中的错误或功能?
  • 有我忽略的东西吗?
  • 有没有更简单的方法来获得jQuery中的预期行为?
提问于
用户回答回答于

使用.prop()是正确的方法。我认为问题在于你在“测试”它的方式。请参见此示例,其中使用切换按钮正确地禁用/启用了按钮,而不管处理程序是通过onclick还是通过jQuery附加的。

window.testFunc = function(event) {
  if (!$('#myButton2').prop('disabled')) {
     alert("hello");
     console.log("hello");
  }
}

$(document).ready(function() {
  var button = $("#myButton2");

  button.on("click", function(event) {
    if (!$(this).prop('disabled')) {
        alert("world");    
        console.log("world");
    }
  });

  $('#toggleButton').click(function() {
	  $('#myButton1').prop('disabled', !$('#myButton1').prop('disabled'));
      $('#myButton2').prop('disabled', !$('#myButton2').prop('disabled'));
  });
  
  $('#tester').click(function() {
  	$('#myButton1').click();
    $('#myButton2').click();
    
  });

})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="button" id="myButton1" value="vanilla button (hello)" onclick="window.testFunc(event)"/>
<input type="button" id="myButton2" value="jquery button (world)"/>
<input type="button" id="toggleButton" value="toggle disabled"/>
<input type="button" id="tester" value="test the buttons"/>
用户回答回答于

为了达到预期的效果,你可以利用.isTriggerjQuery触发的click处理程序来确定事件是否被触发javascript,而不是用户操作。

将属性事件侦听器定义为命名函数,如果调用或不调用,则this可以将条件传递给检查disabled属性。ifalert()

使用.attr("disabled", "disabled")设定disabled为元素,.removeAttr("disabled")以去除属性; .attr("onclick", null)删除事件属性onclick处理程序; .attr("onclick", "handleClick(true)")重置事件属性。

<script src="https://code.jquery.com/jquery-3.1.0.js"></script>

<input type="button" id="myButton" value="button" onclick="handleClick(this)" />
<script>
  function handleClick(el) {
    if (el.disabled !== "disabled")
      alert("Hello")
  }
  var button = $("#myButton");

  button.on("click", function(e) {
    console.log(e);
    if (e.isTrigger !== 3 && !e.target.disabled)
      alert("world");
  });

  button.attr("disabled", "disabled");
  button.attr("onclick", null);
  button.click(); // no output
  
  setTimeout(function() {
    button.removeAttr("disabled");
    button.attr("onclick", "handleClick(button[0])");
    button.click(); // Output : "world" and "Hello"
    // click button during 9000 between `setTimeout` calls
    // to call both jQuery event and event attribute
  }, 1000);

  setTimeout(function() {
    button.attr("disabled", "disabled");
    button.attr("onclick", null);
    button.click(); // no output
  }, 10000);
  
</script>

扫码关注云+社区

领取腾讯云代金券