2016-09-28 8 views
-2

Я превращаю учебную игру в более сильный шаблон приложения и сталкивался с проблемой рефакторинга моих слушателей событий.addEventListener не работает должным образом

В исходном коде, я слушатели установить и обратные вызовы определяются в главной функции:

(function() { 
    "use strict"; 
    GAME.init(); 
    function main() { 
     GAME.stopMain = window.requestAnimationFrame(main); 

     GAME.draw(); 

     GAME.update(); 
    } 

    document.addEventListener("keydown", keyDownHandler, false); 
    document.addEventListener("keyup", keyUpHandler, false); 

    function keyDownHandler(e) { 
     if (e.keyCode === 39) { 
      GAME.inputs.rightPressed = true; 
     } else if (e.keyCode === 37) { 
      GAME.inputs.leftPressed = true; 
     } 
    } 

    function keyUpHandler(e) { 
     if (e.keyCode === 39) { 
      GAME.inputs.rightPressed = false; 
     } else if (e.keyCode === 37) { 
      GAME.inputs.leftPressed = false; 
     } 
    } 

    main(); 
})(); 

Когда я сменил свои слушатель и обратные вызовы за вызов GAME.inputs.init(); и создал этот метод GAME.inputs:

GAME.inputs: { 
    keyDownHandler: function(e) { 
     if (e.keyCode === 39) { 
      this.rightPressed = true; 
     } else if (e.keyCode === 37) { 
      this.leftPressed = true; 
     } 
    }, 

    keyUpHandler: function(e) { 
     if (e.keyCode === 39) { 
      this.rightPressed = false; 
     } else if (e.keyCode === 37) { 
      this.leftPressed = false; 
     } 
    }, 

    init: function() { 
     document.addEventListener("keydown", this.keyDownHandler, false); 
     document.addEventListener("keyup", this.keyUpHandler, false); 
    } 
}; 

Слушатели событий прекратили регистрацию. У меня была эта проблема раньше, и я просто вернулся к старому, но я хотел бы понять, ПОЧЕМУ это не работает.

+0

Я могу назвать несколько возможных причин, но не предоставил [MCVE], так что я не могу сказать, какой из них правильно. (В вашем тестовом случае вы никогда не называете 'init', а функции обработчика событий не делают * ничего * ничего). – Quentin

+1

Вы проверили, что обработчики вызываются? Этот 'init' был вызван? – tcooc

+0

[Кажется, работает] (https://jsfiddle.net/gnvedxo3/)? – Teemu

ответ

0

Вам необходимо позвонить bind, чтобы область действия не являлась документом.

document.addEventListener("keydown", this.keyDownHandler.bind(this), false); 
document.addEventListener("keyup", this.keyUpHandler.bind(this), false); 

и в зависимости от того, как она инициализируется, это может быть на самом деле

document.addEventListener("keydown", this.inputs.keyDownHandler.bind(this), false); 
document.addEventListener("keyup", this.inputs.keyUpHandler.bind(this), false); 
+0

Я не думаю, что это может быть так. В исходном коде (который OP сказал * работал *), 'this' не был переопределен, поэтому обе версии кода должны иметь' this', равный 'document', когда запускается обработчик событий (поскольку вызываются обработчики событий в контексте объекта, к которому они привязаны). – Quentin

+0

В исходном коде я не использовал 'this' ни для чего. Я попробую несколько вариантов привязки и посмотрю, что работает. – Chrinkus

+0

Итак, передавая ссылку 'this' в качестве аргумента метода, не поддерживает ссылку на родительский объект? Думал, что все будет в порядке, пока я не войду в тело внутренней функции. Ahhh .. Я не вводил его, но новые итерации keyHandlers имеют эти «ссылки». – Chrinkus

Смежные вопросы