javascript - Angular 未检测到来自 postMessage 的新窗口中 ngFor 的变化

标签 javascript angular angular8 angular-lifecycle-hooks

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

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);
    }
  }

新窗口监听此 channel 并将消息数据附加到 ngFor 中使用的数组。为了更加安全。每次推送新值以导致重新绑定(bind)时,我都会继续创建一个全新的数组。以下是为新窗口中的组件提供动力的逻辑。

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()”)的按钮,该函数与 postMessage 处理程序具有完全相同的逻辑。

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

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

关于为什么更改检测似乎没有从 postMessage 发生的任何想法?

最佳答案

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);
  });
}

关于javascript - Angular 未检测到来自 postMessage 的新窗口中 ngFor 的变化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58943677/

相关文章:

javascript - 代码在控制台中有效,但在 Hackerrank 中无效

javascript - #container 在第三次#btnAdd 单击后向左移动?

javascript - Chrome 下载 PDF 而不是显示

angular - 适用于(单击)的函数不适用于 ngOnInit()

angular - 如何使用 Angular Material 构建 Ivy ?

javascript - 无法在 asp mvc 中获取站点根 url

css - visibility :hidden in Angular 2

angular - 为什么 projectableNodes 是 any[][]?

typescript - 我们如何在 nz-carousel 中使用 goTo(slidenumber)?如果我想直接转到特定的幻灯片编号

javascript - 为什么当我将链接字符串插入到 html 中时浏览器会自动添加到链接字符串末尾