Typescript 装饰器和 this 上下文

Typescript decorator and this context

我按以下方式在 typescript/angular 中使用装饰器

export function Field({source}){
  return (target, property) => {
    // Some code here
  }
}

那我想这样用

 export class MyClass {

  constructor(private myService: MyService) {}

  @Field({source: () => this.myFn()})
  myProp: string;

  private myFn() { 
   // another code 
   return this.myService.get()
  }
}

显然上下文是错误的,"this" 没有引用 MyClass 的实例。 link 使用 MyClass 实例的上下文的最佳方法是什么?

您可以使用迂回方法访问装饰器中的实例,具体取决于您要执行的操作。在下面的示例中,每次设置 属性 时都会调用传递给装饰器的函数。

装饰器将适用于属性和字段。如果一个字段正在被装饰,那么目标的原型被修改并且该字段被转换成一个 属性 和一个隐藏的支持变量来存储 属性 值。

请注意如何不使用箭头函数来定义 getter 和 setter。这就是在设置 property/field 时检索实例的方式。就个人而言,我经常使用箭头函数,以至于在我尝试之前我什至忘记了这样的事情是可能的。

function Field(srcFunc) {
  return function (target: any, propertyKey: string, descriptor?: PropertyDescriptor) {
    if (descriptor == null) {
      const backingKey = `__${propertyKey}`;
      Object.defineProperty(target, backingKey, { enumerable: false, writable: true });
      Object.defineProperty(target, propertyKey, {
        configurable: true,
        enumerable: true,
        get: function() {
          return this[backingKey];
        },
        set: function(value) {
          this[backingKey] = value;
          srcFunc.call(this);
        }
      });
    }
    else {
      const setOriginal = descriptor.set;
      descriptor.set = function(value) {
        setOriginal.call(this, value);
        srcFunc.call(this);
      }
    }
  }
}

export class MyClass {

  @Field(MyClass.prototype.myFn)
  myProp: string;

  private myFn() { 
   // another code 
  }
}