本文介绍了重新绑定JavaScript事件,并且addEventListener触发两次的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个定义事件侦听器的类方法.为了简单起见,让我们使用以下代码段.

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>

只有一次使用bindEvents()时,一切正常,但是例如在ajax回调中再次调用它会导致侦听器执行两次.因此,这意味着在第二次bindEvents()之后,单击按钮将两次console.log(),依此类推.有办法解决这个问题吗?

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?

我知道我可以在文档上动态"绑定事件并使用e.target进行检查,但是在某些情况下,我需要使用mouseenter/mouseleave事件,但我认为始终拥有这些eventListeners不是一个好主意在文档上.

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...

我还在这里options参数> https://developer.mozilla.org/zh-CN/docs/Web/API/EventTarget/addEventListener ,但没有成功.

Also I have played with the options parameter from here https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener, but without success.

不好意思,如果我在某个地方回答了我,但是我无法在SO和搜索引擎中找到答案.

Excuse me if this was answered somewhere, but I failed to find answer in SO and the search engines.

更新:有没有办法覆盖现有的事件监听器,或者应该使用removeEventListener删除旧的事件监听器,如下面建议的 kcp ?根本没有解决此问题的更优雅的解决方案吗?

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?

推荐答案

在您的情况下,每次执行bindEvents()时,由于定义了新函数,因此将一个全新的处理程序传递给click事件侦听器(无论外观如何,它都是不同的对象).要每次使用相同的处理程序,必须在bindEvents之外定义它,并按名称(通过引用)传递它.可以这样工作:

In your case, each time you execute bindEvents() a completely 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>

但是,对于jQuery,我使用以下方法,该方法允许我指定仅绑定特定容器(上下文或ctx)中的元素:

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.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<button>Click</button>

<div><button>in div </button></div>

在上面的示例中,bindEvents被执行两次,但是第一个按钮仅绑定一次,因为它不在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.

这篇关于重新绑定JavaScript事件,并且addEventListener触发两次的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

07-15 02:57