我正在使用Angular创建一个Chrome扩展程序,以渲染一个弹出窗口。当回调来自Chrome API并且视图绑定中使用的属性由于该回调而改变时,视图绑定不会更新。更为复杂的是,回调不被直接调用,而是包装在Observable中。
如果我呼叫remove
,则视图正在适当更新。我尝试使用NgZone,但可能使用错了-如果我将其包含在创建可观察对象的方法中或将其排除在外,则无效。
ChangeDetectorRef.detectChanges()
ngOnInit() {
this.port = chrome.runtime.connect({ name: 'PopupToBackground' });
// ChromeUtil is an injected service wrapping chrome API calls.
this.chromeUtil.portOnMessage$(this.port).pipe(
tap((x: string) => {
// text is the bound property
this.text = x || 'no data';
// Uncomment line below and everything works.
//this.cd.detectChanges();
})
).subscribe();
}
答案 0 :(得分:1)
onMessage
事件在Angular之外执行,您需要调用zone.run()
来触发更改检测。您几乎拥有了它,但是在错误的位置调用了run()
。
portOnMessage$(port: chrome.runtime.Port) {
return new Observable<any>(subscriber => {
const listener = (msg: any) => this.zone.run(() => subscriber.next(msg));
port.onMessage.addListener(listener);
return {
unsubscribe() {
port.onMessage.removeListener(listener);
}
};
});
}
传递到port.onMessage.addListener()
的回调在Angular之外执行。必须在区域内运行的是此回调。
// Uncomment line below and everything works.
//this.cd.detectChanges();
如果您的组件正在使用OnPush
更改检测,则必须像对待任何外部可观察到的组件一样调用this.cd.markForCheck()
。另一种方法是在模板中使用async
管道。