2010-04-02 48 views
0

我正在研究一個基於Prototype庫的Javascript類。這個類需要觀察一個事件來執行一個拖動操作(當前的拖放控件不適合這種情況),但是我有問題使它停止觀察事件。停止使用JS原型不使用.bind觀察事件(this)

下面是導致此問題的一個樣本:

var TestClass = Class.create({ 
    initialize: function(element) { 
     this.element = element; 
     Event.observe(element, 'mousedown', function() { 
      Event.observe(window, 'mousemove', this.updateDrag.bind(this)); 
      Event.observe(window, 'mouseup', this.stopDrag.bind(this)); 
     }); 
    }, 
    updateDrag: function(event) { 
     var x = Event.pointerX(event); 
     var y = Event.pointerY(event); 
     this.element.style.top = y + 'px'; 
     this.element.style.left = x + 'px'; 
    }, 
    stopDrag: function(event) { 
     console.log("stopping drag"); 
     Event.stopObserving(window, 'mousemove', this.updateDrag.bind(this)); 
     Event.stopObserving(window, 'mouseup', this.stopDrag.bind(this)); 
    } 
}); 

沒有.bind(本),然後this.element是不確定的,但它的活動不停止被觀察(控制檯輸出不會出現,雖然)。

+0

高興的是幫助。我剛更新了我的答案,因爲我注意到'initialize'中的一個(無關的)錯誤,值得一看。 – 2010-04-02 16:35:54

回答

4

bind每次調用它時都會返回一個新的函數引用(這是它的工作:-)),並且如果函數引用是===匹配,stopObserving將只解除處理函數的綁定。

要解決此問題,請記住您作爲屬性綁定的事件處理程序,然後使用該屬性與stopObserving。或者,如果您負責該元素,則可以通過簡單地關閉第三個參數來取消所有處理程序的mousemovemouseup事件。 (請參閱鏈接的文檔以瞭解更多關於將參數設置爲stopObserving的信息)。

因此,要麼:

initialize: function(element) { 
    this.element = element; 
    this.boundUpdateDrag = this.updateDrag.bind(this); 
    this.boundStopDrag = this.stopDrag.bind(this); 
    Event.observe(element, 'mousedown', function() { 
     // Off-topic, but see note at end of answer, unrelated bug here 
     Event.observe(window, 'mousemove', this.boundUpdateDrag); 
     Event.observe(window, 'mouseup', this.boundStopDrag); 
    }); 
}, 
stopDrag: function(event) { 
    console.log("stopping drag"); 
    Event.stopObserving(window, 'mousemove', this.boundUpdateDrag); 
    Event.stopObserving(window, 'mouseup', this.boundStopDrag); 
} 

或者只是

stopDrag: function(event) { 
    console.log("stopping drag"); 
    Event.stopObserving(window, 'mousemove'); 
    Event.stopObserving(window, 'mouseup'); 
} 

但要注意的是,後者移除了所有處理該元素在這些事件(當然,對那些通過原型掛鉤)。


題外話,但請注意,在你的initialize功能的錯誤:它使用this在處理程序mousedown,但不保證this設置爲它應該被設置爲。您需要綁定該匿名函數,或使用initialize中的變量來利用匿名函數是閉包的事實。

如此反覆要麼使用綁定:

initialize: function(element) { 
    this.element = element; 
    this.boundUpdateDrag = this.updateDrag.bind(this); 
    this.boundStopDrag = this.stopDrag.bind(this); 
    Event.observe(element, 'mousedown', (function() { 
     Event.observe(window, 'mousemove', this.boundUpdateDrag); 
     Event.observe(window, 'mouseup', this.boundStopDrag); 
    }).bind(this)); 
}, 

或者使用你無論如何定義一個封閉的事實:

initialize: function(element) { 
    var self; 

    self = this; // Remember 'this' on a variable that will be in scope for the closure 
    this.element = element; 
    this.boundUpdateDrag = this.updateDrag.bind(this); 
    this.boundStopDrag = this.stopDrag.bind(this); 
    Event.observe(element, 'mousedown', function() { 
     // Note we're using 'self' rather than 'this' 
     Event.observe(window, 'mousemove', self.boundUpdateDrag); 
     Event.observe(window, 'mouseup', self.boundStopDrag); 
    }); 
}, 
+0

啊,謝謝。我應該更仔細地閱讀文檔。解除所有處理程序的完美工作。 – PeterBelm 2010-04-02 16:30:29