Вход

Просмотр полной версии : Именованный обработчик события в методе класса


deGeneral
27.11.2019, 17:34
Приветствую всех!

Есть класс, управляющий движением элемента по экрану, в нем метод start():

start() {

document.addEventListener('keydown', (event) => {
... <некий код> ...
});

document.addEventListener('keyup', (event) => {
... <некий код> ...
});
}

Проблема в следующем: функциям-обработчикам нужно дать имена, чтобы в дальнейшем можно было сослаться на них для удаления EventListener. Пробовал делать их методами класса:

onKeyDown(event) {
}

onKeyUp(event) {
}

или даже глобальными:

function onKeyDown(event) {
}

function onKeyUp(event) {
}

- не работает. Только если код функции встраивается inline, тогда все ок.

Как победить проблему?

Aetae
27.11.2019, 18:08
Хранить всё в классе, имеющем специальный метод handleEvent (https://learn.javascript.ru/introduction-browser-events#obekt-obrabotchik-handleevent) и передавать в listener просто this.

deGeneral
27.11.2019, 18:53
Глубокая мысль. Попробую.

deGeneral
27.11.2019, 22:27
Вот она проблемка, определился с ней наконец-то:

class MyClass {

constructor(x) {
this.x = x;
}

onKeyDown(event) { // Если эту функцию привязать к EventListener,
console.log(this); // то this из нее будет смотреть на document, x не виден
}

start() {
document.addEventListener('keydown', this.onKeyDown);
document.addEventListener('keydown', (event) => {
console.log(this); // а отсюда this будет смотреть на объект класса MyClass и прекрасно увидит this.x
});
}

}

window.onload = function() {
let c = new MyClass(5);
c.start();
};

Как объяснить, почему так происходит?
Как сделать так, чтобы из поименованной функции виделся x?

Aetae
27.11.2019, 22:55
Потому что для стрелочной функции this - это конкретно this контекста объявления оной, а для нормальной функции this зависит от условий вызова.
Можно конечно использовать стрелочные функции, но именно для вашего случая и придумали передачу объекта:
class MyClass {
constructor(x) {
this.x = x;
}

onKeyDown(event) {
console.log(this);
}

onKeyUp(event) {
console.log(this);
}

handleEvent(event) {
switch(event.type) {
case 'keydown':
return this.onKeyDown(event);
case 'keyup':
return this.onKeyUp(event);
// ...
}
}

start() {
document.addEventListener('keydown', this);
document.addEventListener('keyup', this);
}
}

window.addEventListener('load', function() {
let c = new MyClass(5);
c.start();
});

deGeneral
27.11.2019, 23:22
Отлично, это как раз самое то, что меня устроит. Спасибо!