回调中的组件属性更改时,绑定未更新

时间:2019-05-01 15:17:54

标签: angular google-chrome-extension rxjs

我正在使用Angular创建一个Chrome扩展程序,以渲染一个弹出窗口。当回调来自Chrome API并且视图绑定中使用的属性由于该回调而改变时,视图绑定不会更新。更为复杂的是,回调不被直接调用,而是包装在Observable中。

如果我呼叫remove,则视图正在适当更新。我尝试使用NgZone,但可能使用错了-如果我将其包含在创建可观察对象的方法中或将其排除在外,则无效。

相关组件代码

ChangeDetectorRef.detectChanges()

相关的ChromeUtil代码

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

1 个答案:

答案 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管道。