Декоратор машинописного текста и этот контекст - PullRequest
0 голосов
/ 27 мая 2020

Я использую декораторы в машинописном тексте / 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. Как лучше всего связать этот контекст с экземпляром MyClass?

1 Ответ

1 голос
/ 27 мая 2020

Вы можете получить доступ к экземплярам в декораторах окольными методами в зависимости от того, что вы пытаетесь сделать. В приведенном ниже примере функция, переданная декоратору, вызывается каждый раз при установке свойства.

Декоратор будет работать как для свойств, так и для полей. Если поле декорируется, то прототип цели изменяется, и поле преобразуется в свойство со скрытой резервной переменной для хранения значения свойства.

Обратите внимание, что здесь не используются стрелочные функции для определения геттер и сеттер. Вот как можно получить экземпляр во время установки свойства / поля. Лично я так часто использую стрелочные функции, что забываю, что что-то подобное было возможно, пока я не попробовал это.

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 
  }
}
...