如何在一个类中删除一个事件监听器?

说我有以下代码:


class Sample {

    constructor() {

        this.value = 'something';

    }


    addClickListener(e) { // e is a dom element


        let func = function(e) {

             //what I want to be able to do:

             this.doThing(e);

    }


        e.addEventListener('click', func, false);

    }


    removeClickListener(e) {


        let func = function(e) {

            //what I want to be able to do:

             this.doThing(e);

        }


        e.removeEventListener('click', func, false);

    }


    doThing(p) { 

    //code

    }


}

我希望能够从'func'中引用类方法并将其传递给它一个参数。对该类的引用(例如,让this = self)不起作用,因为每次调用该函数并更改事件侦听器的签名时,都会对此类进行新版本的引用。


斯蒂芬大帝
浏览 386回答 1
1回答

长风秋雁

要删除事件监听器,您需要保留对要删除的函数的引用:class Sample {    constructor() {        this.value = 'something';        // I've changed it from "let func" to "this.func" so we retain a reference        // I also moved it from addClickListener to the constructor so that we        // don't overwrite our reference when binding more elements to the        // same function        this.func = function(e) {             //what I want to be able to do:             this.doThing(e); // NOTE: You have another bug here. See comments        }    }    addClickListener(e) { // e is a dom element        // Replaced "func" with "this.func"        e.addEventListener('click', this.func, false);    }    removeClickListener(e) {        // Removed the new (unused) function        // Replaced "func" with "this.func"        e.removeEventListener('click', this.func, false);    }    doThing(p) {         //code    }}请注意,我在评论中说:“注意:您在这里还有另一个错误”调用事件侦听器时,上下文(this变量)将更改为发出事件的元素。因此this.doThing将尝试调用doThing该元素e!还要注意的是e元素(传递给参数addClickListener是不一样的e事件(参数传递给this.func)要修复此错误,您需要存储对该类的引用,并在函数定义中使用该引用:    constructor() {        this.value = 'something';        let self = this;        this.func = function(e) {             self.doThing(e);        }    }这里self将不会被覆盖一样this的意志,所以我们可以放心地使用它来引用的类实例更好的解决方案当我重新阅读问题时,我意识到您的函数实际上只是在调用另一个函数。因此,为什么不将要最终运行的功能传递给它addEventListener呢?class Sample {    constructor() {        this.value = 'something';    }    addClickListener(e) {        e.addEventListener('click', this.doThing, false);    }    removeClickListener(e) {        e.removeEventListener('click', this.doThing, false);    }    doThing(p) {         //code    }}请注意,这仍然存在this被调用事件的元素替换的问题,因此doThing您不能说this.doOtherThing调用第二类方法。如果您希望这样做,则需要使用JavaScript的方法创建一个bound方法,.bind()如下所示:class Sample {    constructor() {        this.value = 'something';        this.boundMethod = this.doThing.bind(this);    }    addClickListener(e) {        e.addEventListener('click', this.boundMethod, false);    }    removeClickListener(e) {        e.removeEventListener('click', this.boundMethod, false);    }    doThing(p) {        //code        this.doOtherThing(p);        //more code    }    doOtherThing(p) {        //code    }}另一种选择正如@evolutionxbox指出的那样,您也可以使用箭头功能。此解决方案如下所示:class Sample {    constructor() {        this.value = 'something';        this.boundMethod = p => { this.doThing(p); };    }    addClickListener(e) {        e.addEventListener('click', this.boundMethod, false);    }    removeClickListener(e) {        e.removeEventListener('click', this.boundMethod, false);    }    doThing(p) {        //code        this.doOtherThing(p);        //more code    }    doOtherThing(p) {        //code    }}起作用的原因是箭头函数是绑定方法的简写:x => x + 1;// Is functionally equivalent to:(function(x) {    return x + 1;}).bind(this);许多人没有意识到箭头函数包含隐式bind,并且对于90%的用例而言,这并不重要(例如array.map(x => x + 1),不在乎的值this),但是在类中,该简写实际上具有价值,因此成为在JavaScript类中使用箭头函数以避免覆盖this变量的相当普遍的模式。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

JavaScript