【问题标题】:Angular NgOnChanges behaving weirdlyAngular NgOnChanges 行为怪异
【发布时间】:2021-03-27 23:42:19
【问题描述】:

我有一个父组件通过 Input 向子组件发送数据。 NgOnChanges 不会像我预期的那样工作。我知道它不适用于对象/数组,因为它们是通过引用发送的,因此 Angular 无法检测到更改。

所以我尝试了使用 Object.assign() 将其分配给新对象以创建新引用的解决方法,但它不起作用。

父 TS:

public selectSchedule(index) {
this.oldWeeklyScheduleSelected = this.weeklyScheduleSelected;
if (index != this.weeklyScheduleSelected) {
  this.weeklyScheduleSelected = index;
  this.selectedActivity = undefined;
}
this.http.getDefaultWeekPlanning(this.idOrganisation, this.userId, this.weeklyScheduleCreated[index]
).subscribe((data: any) => {
  if (data === undefined || data.length === 0) {
    this.sendScheduleToChild.scheduleSlot = [];
  } else {
    this.sendScheduleToChild.scheduleSlot = data;
    this.sendScheduleToChild.existingSchedule = true;
    this.sendScheduleToChild = Object.assign({}, this.sendScheduleToChild);
    console.log(this.sendScheduleToChild.scheduleSlot);
  }
}
}

儿童 TS:

@Input() sendScheduleToChild: any;

ngOnChanges(changes: SimpleChanges) {
console.log(changes)
if (this.oldWeeklyScheduleSelected != this.weeklyScheduleSelected && this.oldWeeklyScheduleSelected != undefined) {
  this.daysOfWeek.forEach(e => {
    e.scheduleSlot = [];
  });
  this.scheduleOfEachDay();
} else {
  this.scheduleOfEachDay();
}

if (this.sendScheduleToChild.existingSchedule === true && this.sendScheduleToChild.scheduleSlot.length === 0) {
  this.hoursOfDayDisplay(this.editAgenda);
}
}

oldWeeklyScheduleSelected 和weeklyScheduleSelected 效果很好,因为它们是数字。

sendScheduleToChild 在第一次点击时不会。但它会在之后的第二个,但我的数据会在那个时候搞砸。

console.log(changes) 显示已更改的变量,但在 sendScheduleToChild 的情况下,以前的值和当前值是相同的,而其他两个则不同。

我不明白为什么它一开始没有检测到更改,但由于发送的数据属于同一类型,所以点击 2 次后会检测到更改。

任何帮助表示赞赏。

附注:

我尝试通过更改值来修改对象的引用:

if (data === undefined || data.length === 0) {
    this.sendScheduleToChild.scheduleSlot = [];
  } else {
    this.sendScheduleToChild = {
      scheduleSlot: data,
      existingSchedule: true
    };

但它的行为仍然出乎意料。

【问题讨论】:

  • 你的父组件是否申请了ChangeDetectionStrategy.OnPush?
  • 我不这么认为,我应该把它放在@Component() 中吗?
  • 改为删除它。您的组件依赖于“副作用”,例如 http。所以 OnPush 不应该在这里
  • 好的,我检查了,没有应用到父组件。
  • 好的。简单的解决方法是在 http 回调中添加 changeDetectionRef.markForCheck();。这会通知 Angular 发生了一些变化

标签: angular ngonchanges


【解决方案1】:

您可以尝试围绕输入元素上的变量创建一个设置器。在你的子元素中,做

private _schedule: any;

@Input('sendScheduleToChild')
set sendScheduleToChild(schedule: any) {
   this._schedule = schedule;
}

在你的父组件视图中,简单地做

<childComponent [sendScheduleToChild]="{value}"></childComponent>

ngOnChanges 应该能够在此之后捕获更改。

【讨论】:

    【解决方案2】:

    当您更改输入对象的“参考”时,OnChanges 触发器会发生变化。但是目前您只是更改 value ,您应该将 sendScheduleToChild 分配给新对象。像这样:

    this.sendScheduleToChild = {
     ...sendScheduleToChild,
     scheduleSlot: data;
     existingSchedule: true,
    };
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-06-21
      • 2019-11-03
      • 2012-08-05
      • 2012-12-03
      • 2023-03-02
      相关资源
      最近更新 更多