Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/384.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript Angular未检测到来自postMessage的新窗口中ngFor的更改_Javascript_Angular_Angular8_Angular Lifecycle Hooks - Fatal编程技术网

Javascript Angular未检测到来自postMessage的新窗口中ngFor的更改

Javascript Angular未检测到来自postMessage的新窗口中ngFor的更改,javascript,angular,angular8,angular-lifecycle-hooks,Javascript,Angular,Angular8,Angular Lifecycle Hooks,背景:点击按钮后,我的主页会打开项目中另一个模块的外部窗口(同一来源)。 我还设置了广播频道,以便这两个窗口现在可以通信。现在,如果此窗口已打开&用户再次单击触发按钮,我想将此信息传达给窗口: onAddNewFieldClick() { if (this.window === null) { this.window = window.open(window.location.origin + '/wizard', 'Field Wizard', 'resizable,scr

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

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);
    }
  }
新窗口侦听此通道并将消息数据附加到ngFor中使用的数组。为了更安全。每次推送新值以引起重新绑定时,我都会继续创建一个全新的数组。以下是在新窗口中为组件供电的逻辑

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处理程序完全相同

现在,当我点击这个窗口中的按钮时,我将得到预期的行为:正确数量的“newfieldbox”div将出现在这个新窗口中。但是,当我在主屏幕上按下通过广播频道发布消息的原始按钮时,它不会更新UI以显示正确数量的“新字段框”div。使用断点,我可以看到数组newFields确实包含正确数量的值,但ngFor不会重新渲染

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


您知道为什么更改检测似乎不会从postMessage中发生吗?

事件处理程序可能在外部运行,并且不会触发更改检测。尝试将代码包装到
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);
  });
}