更新、更改或删除/重置Javascript事件侦听器
好的,我正在开发一个小的html5画布绘图库,我有一个小问题,下面是代码(fiddle): 我在这里试图实现的是:当我调用更新、更改或删除/重置Javascript事件侦听器,javascript,html,Javascript,Html,好的,我正在开发一个小的html5画布绘图库,我有一个小问题,下面是代码(fiddle): 我在这里试图实现的是:当我调用drawr.draw()时第二个(或第三个等)以使其覆盖上一个功能。我该怎么做?正如您在我的示例中所看到的,每个实例同时运行 请随意编辑、更新、删除、为错误代码对我大喊大叫等。调用addEventListener将覆盖上一个,或者调用removeEventListener将删除侦听器,仅当为该事件类型指定的处理程序函数严格相等时。一个匿名函数,即使在词汇上完全相同,也不等于在
drawr.draw()时代码>第二个(或第三个等)以使其覆盖上一个功能。我该怎么做?正如您在我的示例中所看到的,每个实例同时运行
请随意编辑、更新、删除、为错误代码对我大喊大叫等。调用addEventListener
将覆盖上一个,或者调用removeEventListener
将删除侦听器,仅当为该事件类型指定的处理程序函数严格相等时。一个匿名函数,即使在词汇上完全相同,也不等于在单独执行该方法期间创建的第二个匿名函数
这里有一个想法:将处理程序定义为闭包中的一个单独函数,如下所示:
obj = function() {
function handler() { /* handle the click; "this" is the element */ }
return {
draw: function() {
this.elt.addEventListener('click', handler);
//draw a bunch of stuff
},
undraw: function() {
this.elt.removeEventListener('click', handler);
//undraw a bunch of stuff
}
};
}();
现在,由于处理程序
始终严格等于自身,因此removeEventListener
将成功删除该处理程序。或者,第二个addEventListener
将不起任何作用(只需将当前处理程序留在原位)
但是,handler
无法访问对象的this
;它将被调用,事件的目标元素作为它的this
。为了将对象的this
放入事件处理程序,您可能会尝试
this.elt.addEventListener('click', handler.bind(this));
但这将无法实现您想要的功能,因为每次调用该方法时,handler.bind(this)
的值都不同,因此您将再次使用冗余的事件处理程序,或者removeEventListener
s,但它们不起作用
如果您确实希望对象的this
在处理程序中,并且不知道如何从事件中检索它,您可以在一些init
函数中初始化处理程序的绑定版本:
obj = {
handler: function(event) { /* handle the click; "this" is the object */ },
draw: function() {
this.elt.addEventListener('click', this.handler);
//draw a bunch of stuff
},
undraw: function() {
this.elt.removeEventListener('click', this.handler);
//undraw a bunch of stuff
},
init: function() {
this.handler = this.handler.bind(this);
return this;
}
}.init();
由于这个.handler
始终与自身相同,因此它可以按预期工作
使用EventListener
解决此问题的一种更优雅的方法是将带有接口的对象传递给addEventListener
,而不是传递给函数,接口是实现特殊命名的handleEvent
方法的任何对象,该方法可以是“this”对象本身,因此您可以执行以下操作:
obj = {
handleEvent: function(event) {
// "this" is the object
if (event.type === 'click') {
// do stuff
}
},
draw: function() {
this.elt.addEventListener('click', this);
},
undraw: function() {
this.elt.removeEventListener('click', this);
}
};
请注意,此
正在传递给addEventListener
。换句话说,我们正在传递对象本身,在它的化身中作为EventListener
的实例,因为它已经实现了handleEvent
handleEvent
是对象的一个成熟方法,因此可以完全访问其所有方法和属性,并且由于此
与自身相同,因此添加、再次添加和删除行为可以按照您的需要工作
我不认为这种方法使用得太多,但它可以使事件处理更加简化,特别是如果在其周围添加一些糖分,例如安排单独的方法来处理每个事件类型:
obj = {
handleEvent: function(event) {
return this[event.type](event); // dispatch to method with name of event
},
click: function(event) {
// handle click; "this" is obj
},
draw: function() {
this.elt.addEventListener('click', this);
},
undraw: function() {
this.elt.removeEventListener('click', this);
}
};
好吧,我来试试。我会让你知道事情的进展!我想用的方式最合乎逻辑吗?使用事件处理程序等?我应该考虑一种不同的方法吗?不太确定你要问的是什么——如果你想处理事件,你需要事件处理程序。我喜欢第一个解决方案,在你标题中的事件听者认为我的方法是我试图得到的。我还没有机会尝试。如果一切顺利,我会回来给你绿色支票。同时,为你所有的时间和努力+1!!好的,我还有一个后续问题:在您的帮助下,(和MDN文档),我成功地创建了覆盖自己的事件侦听器。但是,我希望放弃原来的侦听器,并能够继续使用新的侦听器。根据MDN,忽略第二个侦听器:如果在同一个EventTarget上使用相同的参数注册了多个相同的EventListener,则会丢弃重复的实例….
obj = {
handleEvent: function(event) {
return this[event.type](event); // dispatch to method with name of event
},
click: function(event) {
// handle click; "this" is obj
},
draw: function() {
this.elt.addEventListener('click', this);
},
undraw: function() {
this.elt.removeEventListener('click', this);
}
};