封装在函数中的JavaScript事件侦听器

封装在函数中的JavaScript事件侦听器,javascript,javascript-events,Javascript,Javascript Events,我有一个函数中的事件侦听器。侦听器和发射器都在同一个函数中 触发事件时,变量将递增。到现在为止,一直都还不错。但是,当我多次调用该函数时,侦听器在同一个函数调用中会被触发数次 var test = function() { var completeStatus = 0; $(document).on('gt', function() { console.log(++completeStatus); }); $(document).trig

我有一个函数中的事件侦听器。侦听器和发射器都在同一个函数中

触发事件时,变量将递增。到现在为止,一直都还不错。但是,当我多次调用该函数时,侦听器在同一个函数调用中会被触发数次

var test = function() {    
    var completeStatus = 0;

    $(document).on('gt', function() {
        console.log(++completeStatus);
    });
    $(document).trigger('gt');
}

test();
test();
test();
当函数被调用三次时,它期望输出1三次。但它输出: 0 1. 0 2. 一,

这是为什么?如何获得期望的行为

这里有一个可以尝试的方法。

添加了事件列表,它不会取代以前的列表:

将一个或多个事件的事件处理程序函数附加到 选定的元素

当一个元素有多个事件侦听器时,顺序定义得很好:

绑定到元素的事件处理程序的调用顺序与 他们被绑住了

然后按这个顺序执行它们:

执行附加到匹配元素的所有处理程序和行为 对于给定的事件类型

所以,

  • 第一次调用
    test
    时,添加一个
    completeStatus=0
    的事件侦听器,并触发它。所以你得到了

    0
    
    1 // From the first event listener
    0 // From the second event listener
    
    2 // From the first event listener
    1 // From the second event listener
    0 // From the third event listener
    
  • 第二次调用
    test
    ,前一个事件侦听器具有
    completeStatus=1
    。然后添加第二个事件侦听器,并使用
    completeTestatus=0
    ,然后触发这两个事件。所以你得到了

    0
    
    1 // From the first event listener
    0 // From the second event listener
    
    2 // From the first event listener
    1 // From the second event listener
    0 // From the third event listener
    
  • 第三次调用
    test
    ,第一个事件侦听器具有
    completeStatus=2
    ,第二个事件侦听器具有
    completeStatus=1
    。然后添加第三个事件监听器,其
    completeTestatus=0
    ,并将它们全部触发。所以你得到了

    0
    
    1 // From the first event listener
    0 // From the second event listener
    
    2 // From the first event listener
    1 // From the second event listener
    0 // From the third event listener
    
  • 添加事件列表,但不替换以前的列表:

    将一个或多个事件的事件处理程序函数附加到 选定的元素

    当一个元素有多个事件侦听器时,顺序定义得很好:

    绑定到元素的事件处理程序的调用顺序与 他们被绑住了

    然后按这个顺序执行它们:

    执行附加到匹配元素的所有处理程序和行为 对于给定的事件类型

    所以,

  • 第一次调用
    test
    时,添加一个
    completeStatus=0
    的事件侦听器,并触发它。所以你得到了

    0
    
    1 // From the first event listener
    0 // From the second event listener
    
    2 // From the first event listener
    1 // From the second event listener
    0 // From the third event listener
    
  • 第二次调用
    test
    ,前一个事件侦听器具有
    completeStatus=1
    。然后添加第二个事件侦听器,并使用
    completeTestatus=0
    ,然后触发这两个事件。所以你得到了

    0
    
    1 // From the first event listener
    0 // From the second event listener
    
    2 // From the first event listener
    1 // From the second event listener
    0 // From the third event listener
    
  • 第三次调用
    test
    ,第一个事件侦听器具有
    completeStatus=2
    ,第二个事件侦听器具有
    completeStatus=1
    。然后添加第三个事件监听器,其
    completeTestatus=0
    ,并将它们全部触发。所以你得到了

    0
    
    1 // From the first event listener
    0 // From the second event listener
    
    2 // From the first event listener
    1 // From the second event listener
    0 // From the third event listener
    
  • 因为您使用的是$(document.trigger('gt');所以它在所有文档事件中都启动了触发器事件,这就是为什么增加函数调用以返回输出的原因

    0       //from first function call
    1 0     //from second function call 
    2 1 0   //frm third function call
    .... and so on
    
    解决方案:

    var test = function() {    
        var completeStatus = 0;
        var pageInitialized = false;    
        $(document).on('gt', function() {
            if(pageInitialized) return;
            console.log(++completeStatus);
            pageInitialized = true;
        });
        $(document).trigger('gt');
    }
    
    test();
    test();
    test();
    
    因为您使用的是$(document.trigger('gt');所以它在所有文档事件中都启动了触发器事件,这就是为什么增加函数调用以返回输出的原因

    0       //from first function call
    1 0     //from second function call 
    2 1 0   //frm third function call
    .... and so on
    
    解决方案:

    var test = function() {    
        var completeStatus = 0;
        var pageInitialized = false;    
        $(document).on('gt', function() {
            if(pageInitialized) return;
            console.log(++completeStatus);
            pageInitialized = true;
        });
        $(document).trigger('gt');
    }
    
    test();
    test();
    test();
    

    如上面回复中所述,
    .on()
    添加了事件侦听器,因此在您的示例中,它添加了3次

    除了前面的答案之外,最好避免添加多个侦听器,因为如果无法删除它们,可能会导致内存泄漏。因此,您可以尝试此解决方案,在再次添加之前删除事件侦听器

    var test = function() {    
       var completeStatus = 0;
       var GT_EVT = 'gt';
    
       $(document).off(GT_EVT).on(GT_EVT, function() {
          console.log(++completeStatus);
       });
    
       $(document).trigger(GT_EVT);
    

    }

    如上述回复中所述,
    .on()
    添加了事件侦听器,因此在您的示例中添加了3次

    除了前面的答案之外,最好避免添加多个侦听器,因为如果无法删除它们,可能会导致内存泄漏。因此,您可以尝试此解决方案,在再次添加之前删除事件侦听器

    var test = function() {    
       var completeStatus = 0;
       var GT_EVT = 'gt';
    
       $(document).off(GT_EVT).on(GT_EVT, function() {
          console.log(++completeStatus);
       });
    
       $(document).trigger(GT_EVT);
    

    }

    另一种方法是在每次执行函数时生成唯一的事件和处理程序:

    var test = function() {    
        var completeStatus = 0;
        var uniqid = Math.random().toString(36).slice(-8);
    
        $(document).on('gt' + uniqid, function() {
            console.log(++completeStatus);
        });
        $(document).trigger('gt' + uniqid);
    }
    
    test();
    test();
    test();
    


    但是性能影响呢?使用这种方法有什么优点/缺点吗?

    另一种方法是在每次执行函数时生成唯一的事件和处理程序:

    var test = function() {    
        var completeStatus = 0;
        var uniqid = Math.random().toString(36).slice(-8);
    
        $(document).on('gt' + uniqid, function() {
            console.log(++completeStatus);
        });
        $(document).trigger('gt' + uniqid);
    }
    
    test();
    test();
    test();
    


    但是性能影响呢?使用这种方法有什么优点/缺点吗?

    每次调用
    test
    ,它都会在事件
    gt
    上绑定一个侦听器,并向绑定的所有侦听器触发一个
    gt
    事件。(不仅仅是您之前创建的一个)您更容易理解,只需简短地检查控制台:每次都会创建侦听器,每个侦听器都有自己的
    completeStatus
    变量,因此只需假设您有多个订阅者。请注意,在您的问题中,您有
    ++completeStatus
    ,它产生
    1232 1
    ,在你的小提琴中有
    completeStatus++
    ,它产生
    0102 1 0
    。每次你调用
    test
    ,它会在事件
    gt
    上绑定一个监听器,并向绑定的所有监听器触发
    gt
    事件。(不仅仅是您之前创建的一个)您更容易理解,只需简短地检查控制台:每次都会创建侦听器,每个侦听器都有自己的
    completeStatus
    变量,因此只需假设您有多个订阅者。请注意,在您的问题中,您有
    ++completeStatus
    ,它产生了
    12321
    ,在你的小提琴里有
    CompleteTastus++
    ,它产生了
    0101010
    。非常好用,谢谢!我还可以在触发事件侦听器后立即使用
    $(document.off
    解除其绑定。因此,在给定的时间只有一个事件侦听器。非常有效,谢谢!我还可以使用
    $(document.off)解除事件侦听器的绑定