由装饰者执行方法

时间:2018-02-27 22:57:55

标签: javascript angular typescript angular5

我希望在角度运行DI后,装饰器使用当前组件this执行一个函数。

一个例子:

如果在装饰器上执行,我在this

上没有translateService
export const TesteDecorator = (actionName): any => {

  return (target?: any, propertyKey?: string): void => {

    Observable.timer(5000).subscribe(() => {
      target[propertyKey](); // when i execute here not have translateService on (this)
    });

  };
};

但是如果构造函数上的execute有translateService。

@Component({
  ...
})
export class TesteComponent {

  constructor(
    private translateService: TranslateService
  ) {
    Observable.timer(1000).subscribe(() => {
      this.teste(); // when i execute here translateService is on the (this)
    });
  }

  @TesteDecorator('ACTION')
  teste() {
    console.log(this);
  }

}

有人可以帮助我吗?

1 个答案:

答案 0 :(得分:3)

问题是装饰器是在类声明上执行的,target不是类的实例,而是它的原型,所以它不包含任何字段。

解决此问题的一种方法是包装现有函数以调用额外代码,并从构造函数中调用该方法:

export const TesteDecorator = (actionName): any => {

    return (target?: any, propertyKey?: string): void => {
        var prevFn: ()=> void = target['testeDecoratorHelper'];
        target['testeDecoratorHelper'] = function() {
            prevFn.call(this);
            setTimeout(() => {
                console.log(propertyKey);
                this[propertyKey](); // when i execute here not have translateService on (this)
            }, 10);
        }   

    };
};

export class TesteComponent {
    constructor(private translateService: TranslateService) {
        this.testeDecoratorHelper();   
        setTimeout(() => {
            this.teste(); // when i execute here translateService is on the (this)
        }, 10);
    }
    testeDecoratorHelper() {
    }
    @TesteDecorator('ACTION')
    teste() {
        console.log(this);
    }
    @TesteDecorator('ACTION')
    teste2() {
        console.log(this);
    }
}

上面的实现不适用于派生类型,但它会让你开始。

修改

由于您使用的是Angular,而不是testeDecoratorHelper,因此您还可以使用ngOnInit,它具有自动调用的优势,因此您不必从构造函数中调用它。 (这个建议是10倍)