问题 TypeScript,如何将类方法事件处理程序上下文保持为“this”实例


我在TypeScript中遇到了Classes的问题。每次我必须要听HTML元素事件时,我需要使用Function.bind()将它连接到当前实例。

class VideoAdProgressTracker extends EventDispatcher
{
    private _video:HTMLVideoElement;

    constructor(video:HTMLVideoElement)
    {
        super();
        this._video = video;
        this._video.addEventListener("timeupdate", this.handleTimeUpdateEvent);
    }

    private handleTimeUpdateEvent(event)
    {
        // Something
    }
}

每次当你有5-10个事件时,我不必保存绑定的匿名函数,它将变得一团糟。 我想让它受到约束。

有什么建议么?


9760
2017-11-26 19:13


起源



答案:


您可以将箭头函数用于侦听器方法:

class VideoAdProgressTracker extends EventDispatcher {
    private _video:HTMLVideoElement;

    constructor(video:HTMLVideoElement) {
        super();
        this._video = video;
        this._video.addEventListener("timeupdate", this.handleTimeUpdateEvent);
    }

    private handleTimeUpdateEvent = (event) => {
        // Something
    }
}

这将正常工作,除非您想扩展此类并覆盖其中一个方法。
这样做的原因是使用箭头函数你实际上没有方法,只有用箭头函数分配的属性,它们不是原型的一部分。

例如:

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

编译为:

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

因此,如果您不关心能够轻松覆盖其中一种方法,那么请使用此方法。

如果您想继续使用方法但不想手动绑定所有方法,那么您可以:

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

您还可以检查函数名称以及以某种方式绑定您想要绑定的方法。


14
2017-11-26 19:34



我也发现了这个解决方案。工作得很好! - Nisim Joseph


答案:


您可以将箭头函数用于侦听器方法:

class VideoAdProgressTracker extends EventDispatcher {
    private _video:HTMLVideoElement;

    constructor(video:HTMLVideoElement) {
        super();
        this._video = video;
        this._video.addEventListener("timeupdate", this.handleTimeUpdateEvent);
    }

    private handleTimeUpdateEvent = (event) => {
        // Something
    }
}

这将正常工作,除非您想扩展此类并覆盖其中一个方法。
这样做的原因是使用箭头函数你实际上没有方法,只有用箭头函数分配的属性,它们不是原型的一部分。

例如:

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

编译为:

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

因此,如果您不关心能够轻松覆盖其中一种方法,那么请使用此方法。

如果您想继续使用方法但不想手动绑定所有方法,那么您可以:

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

您还可以检查函数名称以及以某种方式绑定您想要绑定的方法。


14
2017-11-26 19:34



我也发现了这个解决方案。工作得很好! - Nisim Joseph