我有一个定义事件监听器的类方法。为简单起见,我们使用以下代码段。
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>
&#13;
仅使用bindEvents()
一次时一切正常,但是例如在ajax回调中再次调用它会导致侦听器执行两次。所以这意味着在第二个bindEvents()
之后,单击按钮将console.log()
两次,依此类推。有没有办法解决这种问题?
我知道我可以动态绑定事件&#34;动态&#34;在文档上并查看e.target
,但有一种情况我需要mouseenter / mouseleave事件,我不认为总是在文档上有这些eventListener是个好主意。
我已经阅读了以下某处,但似乎是错误的......
.addEventListener方法确保相同的函数引用 不会被多次绑定到相同的元素/事件/捕获 组合
此外,我还使用https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener中的options
参数,但没有成功。
对不起,如果在某个地方得到了解答,但我没能在SO和搜索引擎中找到答案。
更新:有没有办法覆盖现有的eventListeners,旧的应该删除removeEventListener
,如下面建议的 kcp ?对这个问题有更优雅的解决方案吗?
答案 0 :(得分:3)
.addEventListener方法确保相同的函数引用不会多次绑定到相同的元素/事件/捕获组合。
在您的情况下,每次执行bindEvents()
时,都会将全新的处理程序传递给click
事件侦听器,因为您定义了新函数(无论它看起来是否相同,它都是不同的对象)。要在每次必须在bindEvents
之外定义它并使用名称(通过引用)传递时使用相同的处理程序。这有效:
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();
&#13;
<button>click</button>
&#13;
但是使用jQuery我使用以下方法,它允许我指定只绑定特定容器(context或ctx)中的元素:
$.fn.bindEvents = function bindEvents(ctx){
ctx = ctx || this;
$('button', ctx).on('click', function(event){
alert(1);
});
};
$('body').bindEvents();
$('div').bindEvents();
&#13;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button>Click</button>
<div><button>in div </button></div>
&#13;
在上面的示例中,bindEvents
执行了两次,但第一个按钮只绑定了一次,因为它不在div中。如果你点击第二个按钮,它会提醒两次因为满足两个上下文。
答案 1 :(得分:1)
addEventListener
不会覆盖现有的事件侦听器,它只是添加一个新方法,如方法名称所暗示的那样。必须使用removeEventListener
方法删除现有侦听器。
function onClick($event) {
console.log('clicked!');
}
function bindEvents() {
/** Remove event listener first **/
document.querySelector('button').removeEventListener('click', onClick);
document.querySelector('button').addEventListener('click', onClick);
}
答案 2 :(得分:1)
除removeEventListener
外,您还可以使用事件委派。使用此机制事件是通过将事件侦听器附加到父元素来处理的。
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>