Angular 未检测到来自 postMessage 的新 window 中 ngFor 的变化

Angular not detecting changes in ngFor in a new window from a postMessage

背景:单击按钮后,我的主页会打开项目中另一个模块的外部 window(同源)。 我还设置了一个 BroadcastChannel,这样这两个 windows 现在就可以通信了。现在,如果这个 window 已经打开并且用户再次单击触发按钮,我想将其传达给 window:

onAddNewFieldClick() {
    if (this.window === null) {
      this.window = window.open(window.location.origin + '/wizard', 'Field Wizard', 'resizable,scrollbar');
      this.channel = new BroadcastChannel('edit-spec-wizard-channel');
    } else {
      this.channel.postMessage(1);
    }
  }

新的 window 在此通道上侦听并将消息数据附加到 ngFor 中使用的数组。为了更加安全。每次推送新值以导致重新绑定时,我都会继续创建一个全新的数组。这是为新 window.

中的组件提供动力的逻辑
export class EntryComponent implements OnInit, OnDestroy {

  newFieldChannel: BroadcastChannel;
  newFields: number[] = [];
  constructor() { }

  ngOnInit() {
    this.newFieldChannel = new BroadcastChannel('edit-spec-wizard-channel');
    this.newFieldChannel.onmessage = this.newFieldChannelOnMessage.bind(this);
    this.newFields.push(1);
  }

  func() {
    this.newFields.push(1);
    this.newFields = this.newFields.slice();
  }

  private newFieldChannelOnMessage(event: MessageEvent) {
    this.newFields.push(event.data as number);
    this.newFields = this.newFields.slice();
  }

  ngOnDestroy() {
    this.newFieldChannel.close();
  }
}

这是模板 HTML:

<div class="row">
  <div class="col" *ngFor="let newField of newFields">
    <div style="width: 300px; height: 600px; background-color: white;">
      NEW FIELD BOX
    </div>
  </div>
  <button class="btn btn-primary" (click)="func()">Click me</button>
</div>

我还包含了一个触发功能 ("func()") 的按钮,该功能与 post 消息处理程序具有完全相同的逻辑。

现在,当我单击这个 window 中的按钮时,我将得到预期的行为:正确数量的 "NEW FIELD BOX" div 将出现在这个新的 window。但是,当我在主屏幕上按下 post 通过 BroadcastChannel 发送消息的原始按钮时,它不会更新 UI 以显示 "NEW FIELD BOX" div 的正确数量秒。使用断点我可以看到数组 newFields 确实包含正确数量的值,但 ngFor 不会重新呈现。

示例:我单击主页上的按钮以触发 onAddNewFieldClick()。它打开一个新的 window,其中有一个 "NEW FIELD BOX" div。我再次单击此按钮,其中 post 是一条要添加另一条消息的消息。尽管如此,window 上只剩下一个。我现在单击 window 中的按钮来触发函数 "func()." 这现在将呈现 3 "NEW FIELD BOX" divs(最初的来自初始化,来自 post 未呈现的消息,以及单击此按钮的消息)。

为什么更改检测似乎没有从 post 消息发生?

newFieldChannelOnMessage 事件处理程序可能 运行 在 Angular zone 之外,不会触发更改检测。尝试将代码包装在 NgZone.run():

import { NgZone } from "@angular/core";

constructor(private ngZone: NgZone) { ... }

private newFieldChannelOnMessage(event: MessageEvent) {
  this.ngZone.run(() => {
    this.newFields.push(event.data as number);
  });
}