如何在类方法作为回调的类中添加事件处理程序?



如何在类中添加一个带有类方法作为回调的事件处理程序?

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

是的,我知道一些使其工作的怪癖,但是引入这些事件处理程序时的预期方式是什么???我再次有一种苦涩的感觉,没有人真正生活在OOP:-(

在这里供您玩:https://jsfiddle.net/sepfsvyo/1/

事件侦听器回调中的this将是触发事件的元素。如果希望this成为类的实例,则:

将函数绑定到类实例:

使用Function.prototype.bind将创建一个新函数,其this值将始终是您指定的值(类实例):

r.addEventListener('mouseover', this.OnEvent.bind(this));
//                                          ^^^^^^^^^^^

将函数包装在匿名函数中:

var that = this;
r.addEventListener('mouseover', function(ev) { that.OnEvent(ev); });
//                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

或使用箭头函数(因此无需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);

实际上可以将对象作为 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://medium.com/@WebReflection/dom-handleevent-a-cross-platform-standard-since-year-2000-5bf17287fd38

https://www.thecssninja.com/javascript/handleevent

https://metafizzy.co/blog/this-in-event-listeners/

我发现这种方法更清晰,同时在类this内声明事件时也非常明确。 希望我帮助了某人。

@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。在这种情况下,事件从范围冒泡到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/

相关内容

  • 没有找到相关文章

最新更新