如何在使用class-method作为回调的类中添加事件处理程序?
<div id="test">move over here</div>
<script>
oClass = new CClass();
function CClass()
{
this.m_s = "hello :-/";
this.OnEvent = OnEvent;
with(this)
{
var r = document.getElementById("test");
r.addEventListener('mouseover', this.OnEvent); // this does NOT work :-/
}
function OnEvent()
{
alert(this); // this will be the HTML div-element
alert(this.m_s); // will be undefined :-()
}
}
</script>
是的,我知道一些让它工作的怪癖,但是当这些事件处理程序引入时,预期的方式是什么?我又有一种苦涩的感觉,没有人真正活着。
你可以在这里玩:https://jsfiddle.net/sepfsvyo/1/
发布于 2017-05-02 06:47:12
事件侦听器回调中的this
将是触发事件的元素。如果希望this
成为类的实例,则可以:
将函数绑定到类实例:
使用Function.prototype.bind
,将创建一个新函数,它的this
值将始终是您指定的值(类实例):
r.addEventListener('mouseover', this.OnEvent.bind(this));
// ^^^^^^^^^^^
将函数包装在匿名函数中:
var that = this;
r.addEventListener('mouseover', function(ev) { that.OnEvent(ev); });
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
或者使用arrow function (所以不需要that
):
r.addEventListener('mouseover', ev => this.OnEvent(ev));
// ^^^^^^^^^^^^^^^^^^^^^^
注意:正如在下面的评论中提到的,上述两种方法都会向addEventListener
传递一个不同的函数(带有bind
的方法会创建一个新函数,而无名函数显然是!== this.OnEvent
)。如果稍后要删除事件侦听器,则必须存储对该函数的引用:
var reference;
r.addEventListener('mouseover', reference = this.OnEvent.bind(this));
// ^^^^^^^^^^^^
或者:
var reference;
var that = this;
r.addEventListener('mouseover', reference = function(ev) { that.OnEvent(ev); });
// ^^^^^^^^^^^^
然后,您可以删除事件侦听器,如下所示:
r.removeEventListener('mouseover', reference);
发布于 2019-09-29 02:50:37
您实际上可以将对象作为EventListener回调返回,这样JS将在类中搜索handleEvent
方法并相应地执行:
var myInstance = new myClass;
myInstance.addEventListener("mousedown",myInstance);
// To remove the event you can follow the same pattern
myInstance.removeEventListener("mousedown",myInstance);
你必须这样构造你的类:
class myClass {
constructor(){
// Whatever this is supposed to do.
// You can also add events listener within the class this way :
this.addEventListener("mousedown",this);
}
mouseDownEvent(e)(){
// Some action related to the mouse down event (e)
console.log(e.target);
}
mouseMoveEvent(e)(){
// Some action related to the mouse move event (e)
}
mouseUpEvent(e)(){
// Some action related to the mouse up event (e)
}
handleEvent(e) {
switch(e.type) {
case "mousedown":
this.mouseDownEvent(e);
break;
case "mousemove":
this.mouseMoveEvent(e);
break;
case "mouseup":
this.mouseUpEvent(e);
break;
}
}
}
资料来源:
https://www.thecssninja.com/javascript/handleevent
https://metafizzy.co/blog/this-in-event-listeners/
我发现这个方法更清晰,同时在类this
中声明事件也非常明确。希望我帮了什么人。
发布于 2021-11-13 08:45:47
来自@ibrahimmahrir的答案可以完成这项工作,但我想巩固几点。
正如许多JavaScript开发人员难以理解的那样,this
关键字是一个不断变化的目标。在传统的OOP语言中,对象方法是对象所独有的,因此this
被定义为它所附加到的对象。
JavaScript函数更加混杂,并且可以附加到多个对象。在JavaScript中,this
指的是当前正在调用函数的对象,而不一定是函数最初附加到的对象。
对于事件处理程序函数,调用对象是它附加到的元素,而不是原始对象;因此this
指的是元素。通常的安全方法是将对原始对象的引用存储在另一个变量中,该变量通常称为that
oClass = new CClass();
function CClass() {
var that = this; // a reference to the original object
this.m_s = "hello :-/";
this.OnEvent = OnEvent;
var r = document.getElementById("test");
r.addEventListener('click', this.OnEvent);
function OnEvent() {
alert(that); // this is now the object
alert(that.m_s); // this works
}
}
上面的评论是我的更新评论。我还删除了with
语句,该语句贡献不大,并且严重不鼓励使用。
哦,为了更容易测试,我已经将事件更改为click
。
虽然我们对this
感到困惑,但它不一定是开始事情的元素。假设我们现在包含了一个span
<div id="test">click <span>over</span> here</div>
单击span
将触发事件侦听器,即使您实际上没有单击它所附加到的div
。在这种情况下,事件是从span到div冒泡的。
在这里,this
只引用带有事件侦听器的div
元素。如果要引用span
,则需要event.target
function OnEvent(event) { // include event parameter
alert(this); // the element attached
alert(event.target); // the element clicked
alert(that); // this is now the object
alert(that.m_s); // this works
}
这是一个更新的提琴:https://jsfiddle.net/osk083xv/
https://stackoverflow.com/questions/43727516
复制相似问题