当事件处理程序是原型函数时,如何使用removeEventListener?

时间:2015-02-07 19:57:00

标签: javascript event-handling

这是此question的后续行动。问题是我对removeEventListener的调用不起作用。我需要在下面更改哪些内容才能正常工作?

我的自定义对象:

//Custom Editor Example with event listeners
var CE = function (id) {
    'use strict';

    // assume not a valid object
    this.isValid = false;
    this.element = document.getElementById(id);
    if (this.element !== null) {
        this.id = id;
        this.init();
        this.isValid = true;
    }
};


CE.prototype.addEvent = function (event, callback, caller) {
    'use strict';

    // check for modern browsers first
    if (typeof window.addEventListener === 'function') {
        return caller.element.addEventListener(event, function (e) {callback.call(caller, e); }, false);
    }
    // then for older versions of IE
    return this.element.attachEvent('on' + event, function (e) {callback.call(caller, window.event); });
};

CE.prototype.init = function () {
    'use strict';
    this.addEvent('keydown', this.onCustomKeyDown, this);
    // add other event listeners
};

这就是我试图删除事件处理程序的方法:

CE.prototype.removeEvent = function (event, callback, caller) {
    'use strict';
    caller.element.removeEventListener(event, callback, false);
};


CE.prototype.destroy = function () {
    'use strict';
    this.removeEvent('keydown', this.onCustomKeyDown, this);
    // remove other event listeners
};

这是处理事件的原型函数的签名。

CE.prototype.onCustomKeyDown = function onCustomKeyDown(e) {

如果我理解正确,则removeEventListener不能用于删除作为匿名函数的事件处理程序。这是问题吗?我是否需要更改我呼叫addEventListener的方式?

2 个答案:

答案 0 :(得分:5)

  

如果我理解正确,则removeEventListener不能用于删除作为匿名函数的事件处理程序。这是问题吗?

是。添加的函数是匿名函数表达式,而不是callback,因此使用removeEventListener调用callback将不起作用。

  

我是否需要更改我调用addEventListener的方式?

是的,您需要保留对实际处理程序函数的引用,以便稍后将其传递给removeEventListener。基本上有两种方法可以做到这一点:

  • 使用闭包并从remover返回addEvent函数,该函数将取消订阅。
  • 在某处存储对事件处理程序的引用,以便在调用removeEvent方法时通过回调识别它 - 并确保它不会泄漏。

答案 1 :(得分:1)

谢谢@Bergi。

这是他回答中的选项#2。您可以试试JSFIDDLE

//Custom Editor Example with event listeners
var CE = function (id) {
    'use strict';

    // assume not a valid object
    this.isValid = false;
    this.element = document.getElementById(id);
    if (this.element !== null) {
        this.id = id;
        this.customKeyDownHandler = null;
        this.customFocusHandler = null;
        this.init();
        this.isValid = true;
    }
};


/**
 * Initialize an event listener
 */
CE.prototype.addEvent = function (event, callback, caller) {
    'use strict';
    var handler;
    // check for modern browsers first
    if (typeof window.addEventListener === 'function') {
        this.element.addEventListener(event, handler = function (e) {
            callback.call(caller, e);
        }, false);
        return handler;
    }
    // then for older versions of IE
    this.element.attachEvent('on' + event, handler = function (e) {
        callback.call(caller, window.event);
    });
    return handler;
};


/**
 * init object
 */
CE.prototype.init = function () {
    'use strict';

    this.customKeyDownHandler = this.addEvent('keydown', this.onCustomKeyDown, this);
    this.customFocusHandler = this.addEvent('focus', this.onCustomFocus, this);
};

/**
 * remove an event listener
 */
CE.prototype.removeEvent = function (event, callback) {
    'use strict';
    this.element.removeEventListener(event, callback, false);
};


/**
 * destroy object
 */
CE.prototype.destroy = function () {
    'use strict';
    this.removeEvent('keydown', this.customKeyDownHandler);
    this.customKeyDownHandler = null;
    this.removeEvent('focus', this.customFocusHandler);
    this.customFocusHandler = null;
};

/**
 * keydown event handler responds to arrow keys
 */
CE.prototype.onCustomKeyDown = function (e) {
    'use strict';
    // if (e.keyCode === 46) { e.preventDefault(); alert("Del key is invalid"); return false; }
    alert("Hey, easy there! Not so hard!");
    return true;
};

/**
 * focus event handler
 */
CE.prototype.onCustomFocus = function (e) {
    'use strict';
    // if (e.keyCode === 46) { e.preventDefault(); alert("Del key is invalid"); return false; }
    alert("Welcome!");
    return true;
};


ce = new CE('myID'); // allocate custom editor

// do something

// input element will have default behavior, event handlers are removed
ce.destroy();