【问题标题】:Angular not detecting changes in ngFor in a new window from a postMessageAngular 未在 postMessage 的新窗口中检测到 ngFor 的变化
【发布时间】:2020-03-15 12:59:21
【问题描述】:

背景:单击按钮后,我的主页会打开项目中另一个模块的外部窗口(同源)。 我还设置了一个 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);
    }
  }

新窗口侦听此通道并将消息数据附加到用于 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 处理程序具有完全相同的逻辑。

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

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

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

【问题讨论】:

    标签: javascript angular angular8 angular-lifecycle-hooks


    【解决方案1】:

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

    【讨论】:

      猜你喜欢
      • 2018-01-03
      • 2023-04-05
      • 1970-01-01
      • 2021-08-07
      • 2012-05-31
      • 2012-05-29
      • 1970-01-01
      • 2018-09-06
      • 2017-06-23
      相关资源
      最近更新 更多