javascript - Javascript事件addEventListener为相同的函数注册多次;使用 OOP

  显示原文与译文双语对照的内容
67 1

我在使用面向对象的Javascript,同时注册事件监听器。从我对事件侦听器的了解,如果应用到,的函数已经经注册,那么将忽略这个事件侦听器。换句话说,它应该只激发一次。但是代码 below ( 在jsfiddle上也可以看到) 中并没有这样的情况。

https://developer.mozilla.org/en-US/docs/Web/API/EventTarget.addEventListener

多个相同的事件侦听器

如果在相同的EventTarget上使用相同的参数注册多个相同的EventListeners,则会丢弃重复的实例。它们不会引发两次调用,因为重复被丢弃,因这里不需要手动删除with方法。

http://jsfiddle.net/qd1e8f6c/

HTML

<div id="wrapper">
 <input id="t1" type="text"/>
 <input id="btn" type="button"/>
</div>

JS

var namespace = namespace || {};
namespace.event = {
 addListener: function(el, type) {
 var handle = function() {
 switch (type) {
 case"focus": 
 console.log(el.value);
 break;
 case"click":
 console.log(el.id +" was clicked");
 break;
 }
 };
 el.addEventListener(type, handle, false);
 }
};
namespace.ExampleClass = function() {
 this.init = function(el1, el2) {
 el1.value ="123";
 el2.value ="Click Me";
 };
};
var textbox = document.getElementById("t1");
var button = document.getElementById("btn");
var inst = new namespace.ExampleClass();
inst.init( textbox, button );
namespace.event.addListener(textbox,"focus");
namespace.event.addListener(button,"click");
//same handle -- shoudln't it only add the event once?
namespace.event.addListener(textbox,"focus");
namespace.event.addListener(button,"click");

你可以以在代码 above的最后几行中看到,一个叫做 addListener的函数被执行两次,它将一个事件注册。然后,addListener 再次执行。我希望它不会再次被 register 和忽略,但它实际上是寄存器。我不明白名称空间中名为 handle的函数完全相同。我 在 这儿 写错 了 吗?

任何帮助都很有用。非常感谢。

时间:原作者:0个回答

126 5

不能将同一类型/函数对绑定到元素。但是,这不是你所做的,你在每次调用 namespace.addEventListener 函数时都显式地创建新的handler 函数。

你拥有的内容:

namespace.event = {
 addListener: function(el, type) {
 var handle = function() {
 switch (type) {
 case"focus": 
 console.log(el.value);
 break;
 case"click":
 console.log(el.id +" was clicked");
 break;
 }
 };
 el.addEventListener(type, handle, false);
 }
};

你所期望的是什么:

var handle = function(evt) {
 var el = evt.currentTarget;
 switch (type) {
 case"focus": 
 console.log(el.value);
 break;
 case"click":
 console.log(el.id +" was clicked");
 break;
 }
};
namespace.event = {
 addListener: function(el, type) {
 el.addEventListener(type, handle, false);
 }
};

因为第二个实例中只有一个 handle 实例。

命名空间

你所拥有的是名称空间的一种方法,但是大多数时候,JS命名空间是通过模块 Pattern ( ) 实现的。

例如,你甚至不太关心使代码可以以通过这里'命名空间'变量全局访问,因为它只在代码中使用:

var namespace = (function(){
 function handle(evt) {
 var el = evt.currentTarget;
 switch (type) {
 case"focus": 
 console.log(el.value);
 break;
 case"click":
 console.log(el.id +" was clicked");
 break;
 }
 };
 function addListener(el, type) {
 el.addEventListener(type, handle, false);
 }
 function ExampleClass() {
 this.init = function(el1, el2) {
 el1.value ="123";
 el2.value ="Click Me";
 };
 };
 var textbox = document.getElementById("t1");
 var button = document.getElementById("btn");
 var inst = new ExampleClass();
 inst.init( textbox, button );
 addListener(textbox,"focus");
 addListener(button,"click");
//And if you do care about 'inst' being global, you'd explicitly add it to the window.
 window.inst = inst;
//Whatever functions you want to expose as 'namespace' would go here.
 return {
 event: {
 addEventListener: addEventListener
 }
 };
})();
原作者:
...