我正在开发一个基于Prototype库的Javascript类。这个类需要观察一个事件来执行拖动操作(当前的拖放控件不适合这种情况),但我遇到了让它停止观察事件的问题。
以下是导致此问题的示例:
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),那么this.element是未定义的,但是使用它时,事件不会被停止观察(虽然控制台输出确实发生了)。
答案 0 :(得分:4)
bind
都会返回一个新的函数引用(这是它的工作:-)),如果函数引用是===
匹配,stopObserving
将只取消处理程序
要解决此问题,请记住绑定为属性的事件处理程序,然后将该属性与stopObserving
一起使用。或者,如果您负责该元素,则可以通过简单地省略第三个参数来取消mousemove
和mouseup
事件的所有处理程序。 (有关将参数留给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');
}
但请注意,后者删除了该元素上那些事件的所有处理程序(嗯,通过Prototype连接的那些)。
偏离主题,但请注意您的initialize
函数中存在错误:它在this
的处理程序中使用mousedown
,但未确保this
已设置它应该被设置为什么。您需要绑定该匿名函数,或使用initialize
中的变量来利用匿名函数是闭包的事实。
所以要么再次使用bind:
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);
});
},