使用 TypeScript Decorator 创建属性 getter 和 setter

mve*_*and 5 decorator typescript

我想使用 TypeScript Decorator 创建一个属性 getter 和 setter,但我一直坚持定义在属性更改或请求时运行的函数。

如果我的装饰器有以下用法Field.watch:

export class Test {
   ...
   @Field.watch({onSet: this.resetCssCache})
   public layoutId = 0;
   ...
   public resetCssCache() {
      ...
   }
   ...
}
Run Code Online (Sandbox Code Playgroud)

装饰器的实现是:

export class Field {

    public static watch(watchers: { onGet?: () => any, onSet?: (newValue: any, oldValue: any) => any }): Function {
        return (target: any, key: string) => {

            // property getter
            const getter = function() {
                return this['_' + key];
            };

            // property setter
            const setter = function(newVal) {
                if (watchers.onSet) {
                    this['_' + key] = watchers.onSet(newVal, this['_' + key]);
                }
                this['_' + key] = newVal;
            };

            // Delete property.
            if (delete this[key]) {

                // Create new property with getter and setter
                Object.defineProperty(target, key, {
                    get: getter,
                    set: setter,
                    enumerable: true,
                    configurable: true
                });
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

我收到一个错误,@Field.watch({onSet: this.resetCssCache})告诉它this没有定义。

我猜装饰器是在定义级别解释的,而不是在实例级别解释的。有没有办法将非静态方法绑定到装饰器的 onSet 属性?

Tit*_*mir 3

this您无法通过装饰器内部访问方法,您可以使用以下方法传递该方法prototype:

export class Test {

    @Field.watch({onSet: Test.prototype.resetCssCache })
    public layoutId = 0;

    public resetCssCache() {

    }

}
Run Code Online (Sandbox Code Playgroud)

请注意,这意味着当您调用时watchers.onSet(newVal, this['_' + key]);,this内部resetCssCache实际上不是watchers的实例Test。您应该使用调用它,call以便您可以this显式传递watchers.onSet.call(this, newVal, this['_' + key])