2017-08-16 169 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>