使用JS Prototype停止观察事件不能使用.bind(this) [英] Stop Observing Events with JS Prototype not working with .bind(this)

查看:112
本文介绍了使用JS Prototype停止观察事件不能使用.bind(this)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在开发一个基于Prototype库的Javascript类。这个类需要观察一个事件来执行拖动操作(当前的拖放控件不适合这种情况),但是我在停止观察事件时遇到了问题。

I'm working on a Javascript class based on the Prototype library. This class needs to observe an event to perform a drag operation (the current drag-drop controls aren't right for this situation), but I'm having problems making it stop observing the events.

以下是导致此问题的示例:

Here's a sample that causes this problem:

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是未定义的,但有了它,事件不会停止观察(控制台输出确实发生)。

Without .bind(this) then this.element is undefined, but with it the events don't stop being observed (the console output does occur though).

推荐答案

bind 都会返回一个新的函数引用(这是它的工作:-))和 stopObserving <如果函数引用是 === 匹配,则/ a>只会取消挂钩处理程序。

bind returns a new function reference every time you call it (that's its job :-) ), and stopObserving will only unhook the handler if the function reference is an === match.

要修复此问题,记住绑定为属性的事件处理程序,然后将该属性与 stopObserving 一起使用。或者,如果您负责该元素,则可以为 mousemove mouseup取消所有处理程序事件。 (有关将参数省略到 stopObserving 的更多信息,请参阅链接文档。)

To fix this, remember the event handler you bound as a property and then use that property with stopObserving. Or, if you're in charge of that element, you can unhook all handlers for the mousemove and mouseup events by simply leaving off the third parameter. (See the linked docs for more about leaving off parameters to 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连接的那些)。

But note that the latter removes all handlers for those events on that element (well, the ones hooked up via Prototype).

偏离主题,但请注意您的初始化函数中的错误:它在 mousedown c $ c>,但不确保设置为应设置的值。您需要绑定该匿名函数,或使用 initialize 中的变量来利用匿名函数是闭包的事实。

Off-topic, but note that there's a bug in your initialize function: It's using this in the handler for mousedown, but not ensuring that this is set to what it should be set to. You'll need to bind that anonymous function, or use a variable in initialize to take advantage of the fact that that anonymous function is a closure.

所以要么再次使用bind:

So either use bind again:

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));
},

或者使用你正在定义闭包的事实:

Or use the fact you're defining a closure anyway:

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);
    });
},

这篇关于使用JS Prototype停止观察事件不能使用.bind(this)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆