簡體   English   中英

禁用vanilla JavaScript和jQuery中的按鈕

[英]Disabling a button in vanilla JavaScript and in jQuery

香草JavaScript

在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); 只需更改button元素的disabled屬性,但不會禁用實際的click事件。 這意味着只要button.click();就會觸發事件button.click(); 即使按鈕被禁用,也會被調用!

另外,“world”和“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')"/> 

當然,這是一個荒謬的復雜和“hacky”代碼,可以實現像禁用按鈕一樣簡單的功能。


我的問題

  • 為什么jQuery - 不像vanilla JS - 在禁用按鈕時不會禁用事件?
  • 這被認為是jQuery中的錯誤或功能嗎?
  • 我有什么東西可以俯瞰嗎?
  • 有沒有更簡單的方法來獲得jQuery中的預期行為?

要實現預期的結果,您可以在jQuery觸發的click處理程序中使用.isTrigger來確定事件是否由javascript觸發,而不是用戶操作。

定義屬性事件偵聽器作為命名功能,在this可以通過檢查disabled酒店在if條件如果alert()被調用,或者不叫。

使用.attr("disabled", "disabled")在element, .removeAttr("disabled")設置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> 

如果你看一下這些行的jquery-1.12.4.js

handlers: function( event, handlers ) {
    var i, matches, sel, handleObj,
        handlerQueue = [],
        delegateCount = handlers.delegateCount,
        cur = event.target;

    // Support (at least): Chrome, IE9
    // Find delegate handlers
    // Black-hole SVG <use> instance trees (#13180)
    //
    // Support: Firefox<=42+
    // Avoid non-left-click in FF but don't block IE radio events (#3861, gh-2343)
    if ( delegateCount && cur.nodeType &&
        ( event.type !== "click" || isNaN( event.button ) || event.button < 1 ) ) {

        /* jshint eqeqeq: false */
        for ( ; cur != this; cur = cur.parentNode || this ) {
            /* jshint eqeqeq: true */

            // Don't check non-elements (#13208)
            // Don't process clicks on disabled elements (#6911, #8165, #11382, #11764)
            if ( cur.nodeType === 1 && ( cur.disabled !== true || event.type !== "click" ) ) {

您將根據委派類型看到不同的事件處理:

 $(document).on("click", '#btn', function() { console.log("world"); }); $(function () { $('#btnToggle').on('click', function(e) { $('#btn').prop('disabled', !$('#btn').prop('disabled')); }); $('#btnTestClick').on('click', function(e) { $('#btn').click(); }); }); 
 <script src="https://code.jquery.com/jquery-1.12.4.min.js"></script> <button id="btn">Click Me</button> <button id="btnToggle">Enable/Disable button</button> <button id="btnTestClick">Test Click</button> 

當然,如果您附加如下事件:

$('#btn').on("click", function() {
    alert("world");
});

行為不同,看起來很奇怪。

使用.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"/> 

另一個明顯的解決方案是使用vanilla javascript。 僅僅因為你使用jQuery並不意味着所有“必須”使用它完成。 沒有jQuery,有些事情可以做得很好。

編輯:我編輯了片段,展示了如何阻止jquery的.click()實際觸發警報。

您將直接調用click函數3次(button.click()),無論disabled屬性如何都會觸發。

disabled屬性僅響應單擊事件。

請參閱更新的示例:

  var button = $("#myButton"); var button2 = $("#myButton2"); button.prop("disabled", false); button.on("click", function() { alert("world"); button2.prop("disabled", false); }); button2.prop("disabled", true); button2.on("click", function() { alert("world"); button.prop("disabled", true); }); 
 <script src="https://code.jquery.com/jquery-1.12.2.min.js"></script> <input type="button" id="myButton" value="button" onClick="alert('Hello')"/> <input type="button" id="myButton2" value="button2" /> 

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM