Cur*_*rge 3 javascript angular angular-lifecycle-hooks angular8
背景:单击按钮后,我的主页会打开项目中另一个模块的外部窗口(相同来源)。我还设置了一个 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);
}
}
Run Code Online (Sandbox Code Playgroud)
新窗口侦听此通道并将消息数据附加到 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();
}
}
Run Code Online (Sandbox Code Playgroud)
这是模板 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>
Run Code Online (Sandbox Code Playgroud)
我还包括一个按钮,它触发一个函数(“func()”),该函数与 postMessage 处理程序具有完全相同的逻辑。
现在,当我单击此窗口中的按钮时,我将获得预期的行为:正确数量的“新字段框”div 将出现在此新窗口中。但是,当我按下通过 BroadcastChannel 发布消息的主屏幕上的原始按钮时,它不会更新 UI 以显示正确数量的“NEW FIELD BOX”div。使用断点我可以看到数组 newFields 确实包含正确数量的值,但 ngFor 不会重新渲染。
示例:我单击主页上触发 onAddNewFieldClick() 的按钮。它会打开一个新窗口,其中有一个“NEW FIELD BOX” div。我再次单击此按钮,它会发布一条消息以添加另一个消息。尽管如此,窗户上只剩下一个。我现在单击窗口中触发函数“func()”的按钮。这现在将渲染 3 个“新字段框”div(来自初始化的原始 div,来自未渲染的帖子消息的一个,以及来自单击此按钮的一个)。
任何想法为什么似乎没有从 postMessage 发生变化检测?
该newFieldChannelOnMessage事件处理程序可能运行的外部角度带和不触发变化检测。尝试将代码包装在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);
});
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
345 次 |
| 最近记录: |