TypeScript, how to keep class methods event handlers context to “this” instance

前端 未结 2 759
悲&欢浪女
悲&欢浪女 2021-01-01 14:17

I have an issue with Classes in TypeScript. each time I have to listen to an HTML Element events I need to use Function.bind() to connect it to the current instance.

相关标签:
2条回答
  • 2021-01-01 14:31

    You can use arrow functions for the listener methods:

    class VideoAdProgressTracker extends EventDispatcher {
        private _video:HTMLVideoElement;
    
        constructor(video:HTMLVideoElement) {
            super();
            this._video = video;
            this._video.addEventListener("timeupdate", this.handleTimeUpdateEvent);
        }
    
        private handleTimeUpdateEvent = (event) => {
            // Something
        }
    }
    

    This will work fine, unless you want to extend this class and override one of these methods.
    The reason for this is that using arrow functions you don't really have methods, just properties that are assigned with arrow functions, they are not part of the prototype.

    For example:

    class A {
        fn1 = () => { }
        fn2() { }
    }
    

    Compiles to:

    var A = (function () {
        function A() {
            this.fn1 = function () { };
        }
        A.prototype.fn2 = function () { };
        return A;
    }());
    

    So if you don't care about being able to easily override one of these methods, then use this method.

    If you want to stay with methods but don't want to manually bind all methods, then you can:

    constructor(video:HTMLVideoElement) {
        super();
        this._video = video;
    
        for (let key in this) {
            if (typeof this[key] === "function") {
                this[key] = this[key].bind(this);
            }
        }
    
        this._video.addEventListener("timeupdate", this.handleTimeUpdateEvent);
    }
    

    You can also check the function name and somehow prefix methods you'd like to bind.

    0 讨论(0)
  • 2021-01-01 14:47

    You can also cache the controller context. I use this style a lot, when working with d3.js. This way I still have access to the context of the callback, which in d3 refers usually to an element.

    private onClick(): Function {
      controller: this = this;
      return function(event) {
        controller.anotherClassFunction();
      };
    }
    
    private secondFunction(): void {
      this.addEventlistener(this.onClick());
    }
    
    0 讨论(0)
提交回复
热议问题