How do you remove an event listener that uses “this” in TypeScript?

谁都会走 提交于 2019-12-21 07:12:09

问题


In JavaScript, for an event handler that needs access to private members and functions, I can rely on the function scope of those to be accessible within my event handler function, and do something like this:

theElement.addEventListener("click", onClick);

and later:

theElement.removeEventListener("click", onClick);

In TypeScript, I need to use an anonymous function to have this be the containing object, like so:

theElement.addEventListener("click", (event) => this.onClick(event));

In this case, I can't remove the anonymous function from the listening to the event. How do I have an event listener as part of a class (with access to private fields and methods), that I can remove later?


回答1:


First, JavaScript and TypeScript behave the exact same way even if you write like that:

theElement.addEventListener("click", onClick);

Second, this is how you can retain a reference to an anonymous function:

var f = (event) => this.onClick(event);
theElement.addEventListener("click", f);
// later
theElement.removeEventListener("click", f);

If you're dealing with event listeners, there's a useful pattern for your class methods to be bound:

class MyClass {
    init(theElement) {
        theElement.addEventListener("click", this.onClick);
        theElement.addEventListener("click", this.onClick2);
    }
    print() {
        console.log("print");
    }
    onClick() {
        this.print() // possible error (`this` is not guaranteed to be MyClass)
    }

    onClick2 = () => {
        this.print() // no error, `this` is guaranteed to be of type MyClass
    }
}

Keep in mind, however, that this code will create a separate function onClick2 for every object of class MyClass. That can negatively affect your memory usage, if you create lots of MyClass instances and rarely use their onClick listeners.




回答2:


In typescript it is difficult to know what the function call is especially when you "bind" it. Such as:

HTML

<a id="One"></a> <a id="Two"></a>

and some code creating two objects

let x = new MyClass("I am one", "One");
let y = new MyClass("and I am two", "Two");

with MyClass

class MyClass {
    private _myInstance: string;
    constructor(ID: string, domID: string) {
        this._myInstance = ID;
        document.getElementById(domID).addEventListener('click', this.print.bind(this));
    }

    public print() {
        console.log(this._myInstance);
    }
}

You will correct get "I am one" when clicking on the "One" a element and "and I am two" when clicking on the second a element.

The situation is more difficult with removing. You need to add a object variable that has the binding included so the my class changes to:

class MyClass {
    private _myInstance: string;
    private _myDomID: string;
    private _myFunc = this.print.bind(this);
    constructor(ID: string, domID: string) {
        this._myInstance = ID;
        this._myDomID = domID;
        document.getElementById(domID).addEventListener('click', this._myFunc);
    }

    public print() {
        console.log(this._myInstance);
    }

    public cleanUp() {
        document.getElementById(this._myDomID).removeEventListener('click', this._myFunc);
    }

}




回答3:


Already answered question, but IMO the answers here are not well designed regarding to OOP. So, here is my solution:

export class MyClass {

  // create member that holds the function reference
  protected clickEventListener: EventListener;      

  // inject the Element
  constructor(protected theElement: Element) {   
    // wrap the class function `onClick` in an arrow function and assign 
    // to the class member `clickEventListener`   
    this.clickEventListener = () => this.onClick(); 
  }

  onClick() {
    console.log("clicked");
  }

  init() {
    // add the event listener to `theElement` and pass only the reference 
    // of `this.clickEventListener` (no round brackets '()')
    this.theElement.addEventListener("click", this.clickEventListener); 
  }

  destroy() {
    // to remve the event listener also just pass the `clickEventListener` reference
    this.theElement.removeEventListener("click", this.clickEventListener); 
  }

}


来源:https://stackoverflow.com/questions/38023688/how-do-you-remove-an-event-listener-that-uses-this-in-typescript

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!