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

后端 未结 3 1220
星月不相逢
星月不相逢 2021-02-12 11:28

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 functi

相关标签:
3条回答
  • 2021-02-12 11:52

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

    }

    0 讨论(0)
  • 2021-02-12 12:09

    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); 
      }
    
    }
    
    0 讨论(0)
  • 2021-02-12 12:15

    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.

    0 讨论(0)
提交回复
热议问题