admin管理员组文章数量:1326447
I have a class method which defines the event listeners. Let us use the following code snippet for simplicity.
function bindEvents() {
document.querySelector('button').addEventListener('click', (e) => {
console.log('clicked!');
});
}
// Initial event binding
bindEvents();
// Rebind events at some point for dynamically created elements
bindEvents();
<button type="button">Click</button>
I have a class method which defines the event listeners. Let us use the following code snippet for simplicity.
function bindEvents() {
document.querySelector('button').addEventListener('click', (e) => {
console.log('clicked!');
});
}
// Initial event binding
bindEvents();
// Rebind events at some point for dynamically created elements
bindEvents();
<button type="button">Click</button>
Everything works fine when using bindEvents()
only once, however for example calling it again in ajax callback results in listener executed twice. So this means after second bindEvents()
, clicking the button will console.log()
twice and so on. Is there a way I can get around this behavior?
I know I can bind the events "dynamically" on the document and check with e.target
, but there is a situation where I need mouseenter
/mouseleave
events and I don't think it's a good idea to always have those eventListeners
on the document.
I've read somewhere the following, but it seems false...
The .addEventListener method ensures that the same function reference won't be bound more than once to the same element/event/captures bination.
Also I have played with the options
parameter from here https://developer.mozilla/en-US/docs/Web/API/EventTarget/addEventListener, but without success.
Excuse me if this was answered somewhere, but I failed to find answer in SO and the search engines.
UPDATE: Is there a way to overwrite existing eventListeners or old ones should be removed with removeEventListener
like kcp suggested below? Is there more elegant solution to this problem at all?
3 Answers
Reset to default 5The .addEventListener method ensures that the same function reference won't be bound more than once to the same element/event/captures bination.
In your case, each time you execute bindEvents()
a pletely new handler is passed to the click
event listener since you define new function (no matter it looks the same, it is different object). To use the same handler each time you must define it outside bindEvents
and pass it by name (by reference). This works as expexted:
function clickHandler(e){
alert('clicked!');
}
function bindEvents() {
document.querySelector('button').addEventListener('click', clickHandler);
}
// Initial event binding
bindEvents();
// Rebind events at some point for dynamically created elements
bindEvents();
<button>click</button>
However with jQuery I use the following approach which allows me to specify that only elements in a specific container (context or ctx) will be bound:
$.fn.bindEvents = function bindEvents(ctx){
ctx = ctx || this;
$('button', ctx).on('click', function(event){
alert(1);
});
};
$('body').bindEvents();
$('div').bindEvents();
<script src="https://ajax.googleapis./ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button>Click</button>
<div><button>in div </button></div>
In the example above bindEvents
is executed twice but the first button is bound only once since it's not in a div. While if you click on the second button it alerts twice because satisfies both contexts.
addEventListener
does not overwrite existing event listeners, it simply adds a new one as the method name implies. Existing listeners must be removed using the removeEventListener
method.
function onClick($event) {
console.log('clicked!');
}
function bindEvents() {
/** Remove event listener first **/
document.querySelector('button').removeEventListener('click', onClick);
document.querySelector('button').addEventListener('click', onClick);
}
removeEventListener
docs
Apart from removeEventListener
, You can also use Event delegation. Using this mechanism event is handler by attaching event listener to parent element.
var elem = document.querySelector('div');
elem.addEventListener('click', function(e) {
e = e || event
var target = e.target;
if (target.nodeName != 'BUTTON')
return;
console.log('clicked ' + target.textContent);
});
//Simulate addition of dynamic elements
setTimeout(function() {
var newButton = document.createElement('button');
newButton.innerHTML = 'Click 2';
elem.appendChild(newButton)
}, 2000)
<div>
<button type="button">Click</button>
</div>
本文标签: Rebind JavaScript events and addEventListener fires twiceStack Overflow
版权声明:本文标题:Rebind JavaScript events and addEventListener fires twice - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1742214320a2434286.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论