2017-08-16 167 views
1

我一直在試圖找到一種方法來刪除事件偵聽器。我做了一個函數,將一個事件監聽器添加到按鈕,但如果該函數再次運行,我希望事件監聽器被刪除並再次添加。但相反,它只是添加另一個事件監聽器,當我點擊按鈕時,它將運行兩次事件監聽器函數。或者,即使我可以阻止向按鈕添加第二個事件偵聽器也會起作用。刪除重複的事件偵聽器

下面是代碼

<button id="myId">My Button</button> 
 
    
 
    
 
    
 
<script> 
 
    
 
    
 
    
 
myFunction() 
 
myFunction() 
 
    
 
function myFunction() { 
 
    var el = document.getElementById('myId') 
 
    
 
    var listenerFn = function() { 
 
      console.log('My Message') 
 
    } 
 
    
 
    el.removeEventListener('click', listenerFn) 
 
    
 
    el.addEventListener('click', listenerFn) 
 
} 
 
    
 
    
 
    
 
</script>

任何提示將是最有幫助。

UPDATE:

@FathiAlqa​​dasi的回答是最好的,到目前爲止我的問題。但我應該展示更多的代碼。監聽器功能是動態的,可以根據其功能而變化。這是我的意思的另一個例子。

<button id="myId">My Button</button> 



<script> 

myFunctionA() 
myFunctionA() 



function myFunctionA() { 
    var el = document.getElementById('myId') 
    myFunctionB() 
    function myFunctionB() { 
     if (el.innerHTML === 'My Button') { 
      var listenerFn = function() { 
       console.log('My Message 1') 
      } 

       el.removeEventListener('click', listenerFn); 

      el.addEventListener('click', listenerFn); 
     } 

     else { 
      var listenerFn = function() { 
       console.log('My Message 2') 
      } 

       el.removeEventListener('click', listenerFn); 

      el.addEventListener('click', listenerFn); 
     } 
    } 
} 
</script> 

更新2:

謝謝@的代碼。這裏是一個整潔的codebox

<button id="myId">My Button</button> 

<script> 
    var listenerFn; 
    myFunction(); 
    myFunction() 
    function myFunction() { 
     var el = document.getElementById('myId') 
     el.removeEventListener('click', listenerFn); 
     listenerFn = function() { 
      console.log('My Message') 
     } 
     el.addEventListener('click', listenerFn, false); 
    } 
</script> 

回答

0
<button id="myId">My Button</button> 



    <script> 

    myFunction() 
    myFunction() 
    function listenerFn() { 
      console.log('My Message') 
     } 
    function myFunction() { 
     var el = document.getElementById('myId') 

     el.removeEventListener('click', listenerFn) 

     el.addEventListener('click', listenerFn) 
    } 
    </script> 
+0

我已經做了我整個代碼的更新。 – Peter

+0

好吧,你可以嘗試上面的代碼我測試它,它的工作 –

+0

你的代碼確實工作,但不是當功能是動態的,這是我應該在我的第一篇文章中顯示的。閱讀我的更新以瞭解更多以上內容。 – Peter

1

當事件偵聽器的工作,我想將它們存儲在一個對象,這樣我可以跟蹤哪些已經被註冊,輕鬆地刪除它們在必要的代碼。

在你的情況,一個簡單的布爾值將在全局範圍內創建,以檢查是否需要刪除監聽器。 (添加偵聽器後設置爲true)。

<button id="myId">My Button</button> 



<script> 

var removeListener = false; 

myFunction() 
myFunction() 

function myFunction() { 
    var el = document.getElementById('myId') 

    var listenerFn = function() { 
      console.log('My Message') 
    } 

    if (removeListener) el.removeEventListener('click', listenerFn) 

    el.addEventListener('click', listenerFn); 
    removeListener = true; 
} 



</script> 

UPDATE 按照您的更新,我有一個修訂的答案。它仍然不清楚爲什麼你要調用這個函數兩次,但我們會把它當作給定的。

<button id="myId">My Button</button> 



<script> 
var listeners = {}; 

myFunctionA(); 
myFunctionA(); 



function myFunctionA() { 
    var listenerFn1 = function() { //These functions need to be distinct so that we can refer to them when removing 
     console.log('My Message 1') 
    }; 

    var listenerFn2 = function() { //We actually didn't need to move these out from where they were, but its a little easier to read this way 
     console.log('My Message 2') 
    }; 

    function myFunctionB() { 
     if (el.innerHTML === 'My Button') { 
      if (listeners[el]) el.removeEventListener('click', listeners[el]); 
      el.addEventListener('click', listenerFn1); 
      listeners[el] = listenerFn1; //This could be expanded to account for different events, but keeping it simple for this scenario 
     } 
     else { 
      if (listeners[el]) el.removeEventListener('click', listeners[el]); 
      el.addEventListener('click', listenerFn2); 
      listeners[el] = listenerFn2; 
     } 
    } 

    var el = document.getElementById('myId'); 
    myFunctionB(); 
} 
</script> 

這裏的要點是有一個對象,用於存儲觸發事件時調用的函數。對象可以允許不同的事件,如:

var listener = {}; 
var el = document.getElementById('myId'); 

... 

//Check if a click listener exists for el 
if (listener[el] && listener[el].click) { 
    //Remove currently registered listener 
    el.removeEventListener('click', listener[el].click); 
} 
listener[el] = listener[el] || {}; //If listener[el] does not exist, create it 
listener[el].click = function() { 
    //We can use an anonymous function in this case because we do not need to compare it to any other functions 
    console.log('Click 1'); 
}; 
el.addEventListener('click', listener[el].click); 

如果你想允許多個事件附加到一個傾聽者,你要確保你不添加相同的功能不能使用匿名函數兩次。

var listener = {}; 
var el = document.getElementById('myId'); 

... 

var eventHandler1 = function() { 
    console.log('eventHandler1'); 
}; 
var eventHandler2 = function() { 
    console.log('eventHandler2'); 
}; 
//Check if a click listener exists for el that uses eventHandler1 
if (listener[el] && listener[el].click && listener[el].click.includes(eventHandler1)) { 
    //Remove listener with eventHandler1 
    el.removeEventListener('click', listener[el].click.filter(function(val) { 
    return val === eventHandler1; 
    })); 
} 
listener[el] = listener[el] || {}; //If listener[el] does not exist, create it 
listener[el].click = listener[el].click || []; 
listener[el].click.push(eventHandler1); 
el.addEventListener('click', eventHandler1); 
0

在JS中,函數是對象類型,這意味着它們是引用類型。我的意思是每一次你跑你的myFunction;

function myFunction() { 
    var el   = document.getElementById('myId'), 
     listenerFn = function() { 
         console.log('My Message') 
         }; 

    el.removeEventListener('click', listenerFn) 
    el.addEventListener('click', listenerFn) 
} 

您創建一個單獨的listenerFn因此removeEventLister()無法區分它們自removeEventListener()參數必須引用先前設定的事件監聽功能。

您應該如下做;

<button id="myId">My Button</button> 
 

 
<script> 
 

 
function listenerFn() { 
 
    console.log('My Message') 
 
} 
 

 
function myFunction() { 
 
    var el = document.getElementById('myId') 
 
    el.removeEventListener('click', listenerFn) 
 
    el.addEventListener('click', listenerFn) 
 
} 
 

 
myFunction(); 
 

 
</script>