Angular 7:自定义类装饰器破坏了组件范围

时间:2018-10-25 09:43:32

标签: arrays angular typescript angular7

我有一个装饰器,可以在ngOnInit上写一个console.log

log.decorator.ts

export function Log(): ClassDecorator {

    // Decorator Factory
    return (target: Function) => {

        const ngOnInit: Function = target.prototype.ngOnInit;
        target.prototype.ngOnInit = ( ...args ) => {

            console.log('ngOnInit:', target.name);

            if ( ngOnInit ) {
                ngOnInit.apply(this, args);
            }
        };
    };
}

和一个使用HelloComponent并导入@Log()中使用的服务的ngOnInit

hello.component.ts

import { Component, Input, OnInit } from '@angular/core';
import { Log } from './log.decorator';
import { HelloService } from './hello.service';

@Component({
  selector: 'hello',
  template: `<p>Hello! thanks for help and open the browser console for see the error!</p>`,
  styles: [``]
})
// if you remove @Log(), helloService.sayHello() works!
@Log()
export class HelloComponent implements OnInit  {

  constructor(private helloService: HelloService){}

  ngOnInit(){
    this.helloService.sayHello();
  }
}

但这会导致异常:

  

错误TypeError:无法读取未定义的属性'sayHello'

如果我从@Log()中删除了HelloComponent,那就可以了!

装饰器似乎破坏了以下组件的作用域:

ngOnInit.apply(this, args); // line 13: log.decorator.ts

此呼叫之后,this.helloServiceundefined的{​​{1}}中的ngOnInit,但是如果没有HelloComponent@Log()是{{1 }}实例。

我该如何解决?

Stackblitz上的实时示例: https://stackblitz.com/edit/angular-7hhp5n

1 个答案:

答案 0 :(得分:8)

箭头功能强制上下文this为封闭的词法上下文,它是Log函数的执行上下文。

要具有组件上下文,应使用简单的函数表达式:

target.prototype.ngOnInit = function( ...args ) {
   ...
}

Forked Stackblitz