【问题标题】:why EventEmitter doesn't return first value?为什么 EventEmitter 不返回第一个值?
【发布时间】:2020-03-10 06:26:23
【问题描述】:

我有一个 eventemitter 问题,即当我在子类中添加数据并通过 EventEmitter 将数据传递给父类时,我面临一个问题,即当子类添加时父类无法获取第一个数据,第一个数据是在子项中添加第二个数据时,子项仅添加到父项

子组件

    saveData()
        {
         this.dialog.closeAll();
          this.getData();
           const body={
                name:this.model.name,
               age:this.model.age
                 }
          // this.arrayCalendar.push(body);
         this.calendarService.previewdata.emit(body)
               }

父组件

      handleDateClick(arg) {

const data={};
this.dialog.open(AddPatientComponent,{
  data:{data},
  width:"200px",
  height:"300px"

})
 this.calendarService.previewdata.subscribe(message => this.result = message);
console.log("DATA FROM PARENT"+JSON.stringify(this.result))
if(this.result)
{
    this.calendarEvents = this.calendarEvents.concat({ 

    title: this.result.name,
    start: arg.date,
    allDay: arg.allDay
  })
}

}

服务

      constructor() { }
      public previewdata = new EventEmitter();

有人知道这背后的原因吗?

【问题讨论】:

  • 通常,事件发射器的使用方式不同。无论如何,您应该将结果记录在订阅内而不是订阅外。
  • 为什么在服务中使用事件发射器? EventEmitters 用于绑定到 HTML 中的事件。如果您在代码中订阅它,则可以使用某种Subject

标签: angular


【解决方案1】:

您应该将依赖于 EventEmitter 值的代码移动到 subscribe 块内。

this.calendarService.previewdata.subscribe(message => this.result = message);
console.log("DATA FROM PARENT"+JSON.stringify(this.result))
if(this.result)
{
    this.calendarEvents = this.calendarEvents.concat({ 
    title: this.result.name,
    start: arg.date,
    allDay: arg.allDay
  })
}

应该是

this.calendarService.previewdata.subscribe(message => {
 this.result = message;
 console.log("DATA FROM PARENT"+JSON.stringify(this.result))
    if(this.result)
    {
        this.calendarEvents = this.calendarEvents.concat({ 
        title: this.result.name,
        start: arg.date,
        allDay: arg.allDay
      })
    }
});

【讨论】:

  • 但是我遇到了一个问题。那就是当我添加孩子时,我得到了多次名称例如:第一次单击,名称将是一次,第二次添加一个事件,两次获取事件名称
  • @CodeIgniter 你在哪里使用这个代码块?它通常应该在 ngOnInit 内部。如果您在类函数中订阅,请确保您正确调用它。
  • 服务进入handleDateClick(arg)的结果
  • 从这里我把名字放到前端,但是没有时间子添加数据,从服务中检索相同的数据计数或者说相同的没有:它调用服务的次数
  • @CodeIgniter 我不完全确定您要做什么,但是如果您在函数内部订阅,请确保在发出事件之前执行该函数。如果 subscribe 内部的部分被多次调用,那么您发出事件的次数可能比您需要的次数多。
【解决方案2】:

老实说,我建议进行一些认真的重构。如果你想使用emitter 而不使用服务,那是一些奇怪的设计。

其次,不要订阅处理点击的函数。如果您没有正确退订,这可能会导致奇怪的行为,例如您现在遇到的情况。

如果您想使用服务,请删除 emitter 并将其替换为一些主题和可观察的。

服务:

private _previewData: Subject<any> = new Subject<any>(); //use proper type instead of any
previewData$: Observable<any> = this._previewData.asObservable(); //same here

constructor() {}

// and correct type here instead of any
pushUpdate(dialogData: any): void {
  this._previewData.next(dialogData);
}

孩子:

saveData(): void {
  // I'm not sure what dialog you use but I have a feeling that the code below
  // should be moved to subscribe or then
  this.dialog.closeAll();
  this.getData();

  const body = {
    name:this.model.name,
    age:this.model.age
  }

  this.calendarService.pushUpdate(body);
}

家长:

ngOnInit() {
  this.calendarService.previewData$
    .pipe(
      // Add console log to see what data are pushed
      tap(data => console.log('previewData:', data)),
      // Remove if it fails for no obvious reason and do the check in subscribe
      filter(data => !!data)
    )
    .subscribe(message => {
      // Do whatever you want to do with your data here
      this.result = message

      if (this.result) {
        this.calendarEvents = this.calendarEvents.concat({ 
          title: this.result.name,
          start: arg.date,
          allDay: arg.allDay
       });
    });
}

handleDateClick(arg) {
  const data={};
  this.dialog.open(AddPatientComponent, {
    data:{data},
    width:"200px",
    height:"300px"
  });
  // It looks like you are using Angular Material, have you tried 
  // handling data returned from dialog in aferClosed() observable?
  // dialog.afterClosed().subscribe(result => {...});
}

【讨论】:

  • 他也可以直接订阅subject(_previewData),而不是去获取.asObservable()的新属性?实际上我经常看到这种模式..这是什么原因?
  • 当然可以,但这不是最好的方法。这是一篇很好的文章:medium.com/@benlesh/…
  • 您确定要在管道内使用过滤器吗?
  • 不带它试试看,它应该替换if(this.result)。我会更新我的答案,检查替代方案
  • 你能提供stackblitz吗?没有它很难说
猜你喜欢
  • 2017-09-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-11-12
  • 1970-01-01
  • 1970-01-01
  • 2023-03-18
相关资源
最近更新 更多