2014-01-13 66 views
-2

我试图解决一个非常简单的任务,但坚持使用JQuery行为。启用后禁用的按钮引发点击事件

我有一个HTML按钮,我禁用它(添加禁用属性),它被点击后,以防止多次点击,做一些长时间运行(即更新DOM与很多元素),并启用按钮。

问题是,即使在禁用了按钮的jQuery队列上的所有点击和提高它成为激活之后我的点击处理程序。

根据JQuery的文档不应该提高对残疾元素的事件。

贝娄是我的代码。打开JS控制台,在按钮上单击两次,在控制台中注意两个“START - ”消息。

<div> 
<button id="mybtn" type="button">Find</button> 
</div> 

var btnElement = $('#mybtn'); 
btnElement.click(doClick); 

      function doClick() { 
       var btnElement = $('#mybtn'); 
       btnElement.attr('disabled', true); 

       console.log('START --' + Date()); 
       for (var i = 0; i < 70000; i++) { 
        var el = $('#mybtn'); 
        var w = el.width(); 
        w += 10; 
       } 
       console.log('STOP --' + Date()); 
       el.attr('disabled', false); 
      } 
+3

后您的代码在这里,请不要试图回避,并链接到的jsfiddle时发布您的代码的SO规则。 – j08691

+0

如何添加小提琴链接而不发布任何代码? – DontVoteMeDown

+2

@DontVoteMeDown通过欺骗它并包装链接反引号。 – brbcoding

回答

1

这里是我的解决方案http://jsfiddle.net/DRyxd/8/

var btnElement = $('#mybtn'); 
var buttonIsBusy = false; 

function doHeavyJob() { 
    console.log('START --' + Date()); 
    for (var i = 0; i < 70000; i++) { 
     var el = $('#mybtn'); 
     var w = el.width(); 
     w += 10; 
    } 
    var timeoutId = setTimeout (unblockTheButton, 0); 
    console.log('STOP --' + Date()); 
} 

function unblockTheButton() { 
    console.log('unblockTheButton'); 
    btnElement.attr('disabled', false); 
    buttonIsBusy = false; 
} 

function doClick() { 
    console.log('click', buttonIsBusy); 
    if (buttonIsBusy) { 
     return; 
    } 

    btnElement.attr('disabled', true); 
    buttonIsBusy = true; 

    var timeoutId = setTimeout (doHeavyJob, 0); 
} 


btnElement.click(doClick); 

这里的问题是,单击处理函数还没有结束和浏览器还没有刷新DOM。这意味着block尚未应用于该按钮。您可以尝试推你的重码出当前情况下是这样的:

function someHeavyCode() { 
    /* do some magic */ 
} 
var timeoutId = setTimeout(someHeavyCode, 0); 

这将推动你的重码出当前context.Letting浏览器先更新DOM,只执行重码之后。

虽然执行重码

,浏览器(至少铬)在其他地方(或最可能的其他线程)保持所述用户输入队列的某个地方。一旦繁重的代码完成 - 它会向DOM提供所有排队事件。我们需要以某种方式忽略这些事件。我再次使用setTimeout和0时间。让浏览器执行排队之前解锁按钮。

警告但与这种技术非常小心。浏览器仍然会被阻止,如果你产生了很多这样的块,它可能会挂起。 另请参阅此Why is setTimeout(fn, 0) sometimes useful?并考虑使用webworkers。

P.S.以这种方式阻止用户输入并不是一个好方法,试着重新思考你将要做什么,可能有更好的解决方案。

+0

谢谢队友,你救了我几天头痛。 – user3191484

+0

尽管这个解决方案非常棒,但它似乎不适用于Firefox(MacOS版本54.0.1)。 –

+1

@TadayoshiSato很好,因为它是在回答说 - 考虑使用webworkers https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Using_web_workers –