【问题标题】:How do I prevent "duplicate" events from firing in jQuery?如何防止在 jQuery 中触发“重复”事件?
【发布时间】:2016-02-03 19:28:54
【问题描述】:

我有一个连接到各种事件的事件处理程序,以确保它在各种情况下被触发。

var allChangeEvents = "focus blur select change click dblclick mousedown mouseup keypress keydown keyup";
$("#myTextbox").on(allChangeEvents, function() {
    console.log("Event fired.");
});

您会注意到,定期与<input type="text" id="myTextbox" /> 交互(单击、敲击、聚焦等)实际上会导致事件被多次触发。如果正在运行的代码变得非常大,那么这可能会损害性能。有什么方法可以防止事件被触发这么多次,而不必删除我的大量事件类型?

【问题讨论】:

    标签: javascript jquery event-handling throttling debouncing


    【解决方案1】:

    一种选择是限制(或去抖动)调用,以便每个时间段只发生一次调用。一个简单的实现如下(不过,可以找到更好的实现here)

    function debounce(fn,time){
        var timerId = null;
        return function(e){
            if(timerId)
                return;
    
            timerId = setTimeout(function(){
                fn(e);
                timerId = null;
            },time);
        }
    }
    

    而使用会是

    var allChangeEvents = "focus blur select change click dblclick mousedown mouseup keypress keydown keyup";
    $("#myTextbox").on(allChangeEvents, debounce(function(e) {
        console.log("Event fired.");
    },300)); 
    

    如您所见,此示例将导致您的事件处理函数不超过每 300 毫秒发生一次。这是限制执行密集功能频率的好方法。

    下面是一个实际的例子

    var allChangeEvents = "focus blur select change click dblclick mousedown mouseup keypress keydown keyup";
    $("#myTextbox").on(allChangeEvents, debounce(function(e) {
        console.log("Event fired.");
    },300));
    
    
    function debounce(fn,time){
        var timerId = null;
        return function(e){
            if(timerId)
                return;
            
            timerId = setTimeout(function(){
                fn(e);
                timerId = null;
            },time);
        }
    }
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    <input type="text" id="myTextbox" />

    【讨论】:

    • 谢谢。我不得不说,我个人认为您的实现比您提供的链接中的实现更容易理解。您必须是 JavaScript 专业人士才能理解这些内容,而您的示例清晰简洁。
    • 我的想法很幼稚——它改变了函数的调用位置,并可能导致奇怪的行为。
    • 这是否意味着它将函数带出其先前的上下文?
    • 有点,对于事件处理程序,它可以正常工作 - 它通过事件 (e),这就是您所需要的。在更通用的意义上它不会工作得那么好 - 链接版本会。
    【解决方案2】:

    根据文档:http://api.jquery.com/event.stopimmediatepropagation/

    如果您的函数以调用结束 event.stopImmediatePropagation(); 一旦一个被处决,其他的就不会开火。

    【讨论】:

    • 这仅适用于冒泡“DOM 树”的事件,不适用于同一元素上的多个单独事件。例如,如果&lt;button&gt; 在&lt;div&gt; 内,stopImmediatePropagation() 将起作用,并且每个事件都连接到onClick。默认情况下,单击按钮会触发按钮事件,然后“传播”到 div 并触发其事件。在按钮事件处理程序中运行 stopImmediatePropagation() 将阻止 div 点击事件触发。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-09-17
    • 2018-12-01
    • 2019-09-25
    • 1970-01-01
    • 2012-12-16
    相关资源
    最近更新 更多