打字稿:通过回调设置对象成员奇怪地失败

时间:2016-09-22 14:29:09

标签: javascript angular typescript

我有一个非常奇怪的问题,我还没有找到原因。我尝试在Angular 2中显示一个文本框组件,您可以在单击按钮时为其提供消息,按钮标签和调用的回调。

这是我的组件:

@Component({
  selector: 'text-box',
  templateUrl: './textbox.component.html',
  styleUrls: ['./textbox.component.styl']
})
export default class TextBoxComponent implements AfterViewInit {
  content: String;
  btnCaption: String;
  callback: () => void;

  constructor(@Inject(TextBoxService) private service: TextBoxService) {
  }

  ngAfterViewInit(): void {
    this.service.init(this.show);
  }

  public show(message: String, btnCaption: String, callback: () => void) {
    this.content = message;
    this.btnCaption = btnCaption;
    this.callback = callback;
    // (1)
    // set opacity 1
  }

  public btnOnClick() {
    // (2)
    this.callback();
    this.dismiss();
  }

  public dismiss() {
    // set opacity 0
  }
}

组件是单例,无法注入,因此您不能简单地从外部调用组件上的show()。因此,我添加了一个服务并将方法引用到其中(请参阅组件的ngAfterViewInit()方法):

@Injectable()
export default class TextBoxService {
  private showCallback: (m: String, b: String, c: () => void) => void;

  public init(showCallback: (m: String, b: String, c: () => void) => void) {
    this.showCallback = showCallback;
  }

  public show(message: String, btnCaption: String, callback: () => void) {
    this.showCallback(message, btnCaption, callback);
  }
}

它由另一个这样的服务调用:

this.textBoxService.show(
  'Wollen Sie einen Kredit aufnehmen?',
  'Ja', () => {
    ziel.activate();
    this.activatedEvents.set(event, ziel);
    this.inputService.kreditInput.summe = ziel.getPrice() - ziel.getLiquidFunds();
    this.inputService.kreditInput.startdatum = date;
  });

但是,当调用上面的按钮时,文本不会更新,监听器也不会附加到按钮上(显示this.callback() is not a function)。我调试了它(将console.log()放在组件中的(1)和(2)上)并发现两个方法都被正确调用。在(1)成员contentbtnCaptioncallback被正确设置 - 但在(2)上,这些成员是未定义的!

我尝试用function()语法替换fat-arrow-syntax,但没有成功。我也尝试对show()内的字符串进行硬编码,但是当通过buttonClick访问它时,它仍然是未定义的。

似乎在(1)和(2)上有两个不同的对象被访问。我不知道这种行为的原因是什么。有什么想法吗?

1 个答案:

答案 0 :(得分:1)

应该按设计作为回调传递的类原型方法(如在this.service.init(this.show)中)应定义为箭头类属性:

public show = (message: String, btnCaption: String, callback: () => void) => { ... };

或受到班级建设的约束:

constructor(@Inject(TextBoxService) private service: TextBoxService) {
  this.show = this.show.bind(this);
}

或者,装饰器可用于更整洁的语法,例如, @autobind from core-decorators