简体   繁体   English

Typescript 装饰器和这个上下文

[英]Typescript decorator and this context

I am using decorators in typescript/angular in the following way我以下列方式在 typescript/angular 中使用装饰器

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

Then I want to use it this way那我想这样用

 export class MyClass {

  constructor(private myService: MyService) {}

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

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

Obviously the context is wrong and "this" does not refer to the instance of MyClass.显然上下文是错误的,“this”不是指 MyClass 的实例。 What is the best way to link this context with the instance of MyClass?将此上下文与 MyClass 的实例联系起来的最佳方法是什么?

You can get access to instances in decorators with roundabout methods depending on what you're trying to do.您可以使用迂回方法访问装饰器中的实例,具体取决于您要执行的操作。 In the example below the function passed to the decorator is called every time the property is set.在下面的示例中,每次设置属性时都会调用传递给装饰器的 function。

The decorator will work for both properties and fields.装饰器适用于属性和字段。 If a field is being decorated then the prototype of the target is modified and the field is converted into a property with a hidden backing variable to store the property value.如果正在修饰字段,则修改目标的原型,并将字段转换为具有隐藏支持变量的属性以存储属性值。

Note how this does not use arrow functions to define the getter and setter.请注意,这不使用箭头函数来定义 getter 和 setter。 This is how it the instance can be retrieve at the time the property/field is getting set.这就是在设置属性/字段时可以检索实例的方式。 Personally, I use arrow functions so much I forget something like this was even possible until I tried it out.就个人而言,我经常使用箭头函数,以至于在我尝试之前我都忘记了这样的事情是可能的。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM