2013-09-22 4 views
2

Я новичок в javascript, и я столкнулся со следующей проблемой, которую я не смог найти в предыдущих ответах после многократного поиска (надеюсь, что это не дубликат).Невозможно удалить (связанный) прослушиватель событий

У меня есть следующий модуль/класс. Предположим, что я пытаюсь реализовать компонент, который можно перетаскивать по экрану. Когда пользователь нажимает на него первый раз, мы начинаем слушать события mousemovewindow, чтобы узнать, куда движется пользователь. Как только пользователь освобождает мышь, мы хотим удалить прослушиватели событий в окне. Код довольно прост, и он работает, если я просто закодирую его за пределами iife. Однако в настоящее время removeEventListener просто не работает. Думаю, это может иметь какое-то отношение к clousure, scope или что-то в этом роде, но я полностью его не понимаю. Большое спасибо заранее, вот код:

MyClass.js

var myNamespace = myNamespace || {}; 
(function(myNamespace){ 

var onMouseDragDown = function(e){ 
      window.addEventListener("mousemove", onMouseDragMove,true); 
      window.addEventListener("mouseup", onMouseDragUp,false); 
     }; 

    var onMouseDragUp = function(e){ 
// This code executes, but the events CONTINUE to be triggered after removing the event listener 

//The following lines do not seem to have any effect whatsoever even though they are executed when the user releases the mouse button 
     window.removeEventListener("mousemove", onMouseDragMove, true); 
     window.removeEventListener("mouseup", onMouseDragUp,false); 
    }; 

    var onMouseDragMove = function(e){ 
     console.log('moving'); 
    }; 

    myNamespace.MyClass = function(param){ 
     this._param = param; 
     this._div = document.createElement('div'); 
     this._div = .... 

     this._div.addEventListener('mousedown', onMouseDragDown.bind(this), false); 
    } 

    myNameSpace.MyClass.prototype.getDiv = function(){ 
     return this._div; 
    } 
)(myNameSpace); 

Index.html

...

 function onCreateNewDocumentClicked(event){ 
      var myObject = new myNamepace.MyClass(someParams); 
      document.body.appendChild(mdi.getDiv()); 
     } 
+0

фрагмент кода является неполным, я понятия не имею, где вы выполняете этот код. с помощью 'var onMouseDragDown = function (...)', код внутри этого тела функции не будет выполнен – jasonslyvia

+0

Я отредактировал код, чтобы вы могли видеть, как я создаю объект MyClass из index.html , Код именованных функций (var onMouseDragMove) выполняет только то, что событие продолжает запускаться даже после выполнения wind.removeEventListener .... –

+0

Я вижу, тогда вы, вероятно, должны добавить 'this._div.addEventListener ('mouseup' , onMouseDragUp .bind (this), false); 'в определении' myNamespace.MyClass' – jasonslyvia

ответ

4

Чтобы удалить прослушиватель событий, вы должны указать точную функцию, которую вы предоставили при ее добавлении.
То, что здесь происходит, что привязка() создает новую функцию каждый раз, так что на самом деле:

someFunc.bind(someObj) !== someFunc.bind(someObj) 

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

так хранить слушателя, когда вы добавляете его, чтобы иметь возможность удалить его позже:

var someListener = someFunc.bind(someObj); 
element.addEventListener("--", someListener) ; 

// then, later : 
element.removeEventListener('--', someListener); 

я сделал короткий демо здесь, при нажатии на первую кнопку будет оповещать «привет».
Мы видим, что, удалив слушателя с новым вызовом bind, он не удаляет его.
Затем удаление хранимой функции выполняет задание.

http://jsbin.com/EjevIQA/2/edit

Edit: вам не нужно, чтобы добавить/удалить слушателю каждый Div вы хотите тащили. вместо этого вы можете просто прослушать щелчок в окне и использовать информацию о событии «target» , в которой будет указано, какой из них был нажат.
Возможно, вам захочется прекратить распространение/предотвратить по умолчанию, когда он обрабатывается div , который щелкнул, я не знаю.

обработчик событий будет выглядеть следующим образом:

function handleMouseDown(e) { 
    // you might check here which button was clicked (0=left, 2=right) 
    var button = e.button; 
    // retrieve the target 
    var target = e.target ; 
    // check if the target is an object we want to drag 
    ... 
    ... return otherwise. 
    // do some things to initialize the drag. 
    ... 
    // you might want to prevent the click to bubble/trigger default behaviour : 
    e.stopPropagation(); 
    e.preventDefault(); 
} 

вы установите его раз и навсегда на окне или документа объекта:

document.addEventListener("mousedown", handleMouseDown) 

Я сделал маленькую демонстрацию здесь, нажмите на div, чтобы увидеть, что он был идентифицирован:
http://jsbin.com/ilavikI/2/edit

+0

Да, это было именно то, что происходило. То, что мне не нравится в этом решении, состоит в том, что каждый экземпляр будет содержать новую ссылку на функцию, что в значительной степени увеличивает след. Есть ли способ избежать этого таким образом, что я все еще могу связать функцию? Если я попытаюсь объявить его с помощью .bind (this) из объявления, функция привязана к окну вместо экземпляра моего класса, так как это окно, которое на самом деле выполняет IIFE. –

+0

Я редактировал для решения, которое позволяет добавлять/удалять прослушиватели событий при каждом нажатии. – GameAlchemist

1

Мог ли я т быть, что ваш

.bind(this) 

в

this._div.addEventListener('mousedown', onMouseDragDown.bind(this), false); 

не возвращает ссылку на ту же функцию вы удаляете?

+0

Я определенно считаю, что это часть проблемы/решения. Я должен, вероятно, сохранить ссылку на связанную функцию и удалить ее, поскольку .bind скорее всего создаст новую ссылку функции с новым закрытием. –

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