如果在查看另一个组件时数据发生更改,则组件DOM不会更新

时间:2019-02-09 16:33:07

标签: angular rxjs electron

我有一个包含几个组件的应用程序,每个组件异步显示不同的数据。我正在使用routerLink在不同组件之间导航。

问题在于,如果当组件A中的数据发生更改时我当前正在查看组件B,则返回组件A时,DOM不会使用新数据进行更新。(ngFor列表将继续显示test1,test2但是,使用console.log,当我查看组件B时,我可以在Dev Tools中看到组件A仍在接收数据。如果在接收到新数据时我在组件A中, DOM已更新,新数据正确显示。

我有什么需要做的,以确保在导航回组件时刷新DOM?我想我可能可以检测到NavigationEnd并将数据分配给它自己。有什么我想念的吗?

谢谢,这是代码:

组件A

import { Component, OnInit, ChangeDetectionStrategy, NgZone } from '@angular/core';
import { DataService } from '../../services/data.service';

@Component({
  selector: 'app-metars',
  templateUrl: './metars.component.html',
  styleUrls: ['./metars.component.scss'],
  changeDetection: ChangeDetectionStrategy.Default
})
export class TestComponent implements OnInit {

  public dataArray = ['test1', 'test2'];

  constructor(private _dataService: DataService, private zone: NgZone) { }

  ngOnInit() {
    this._dataService.data$
    .subscribe( data => {
        this.zone.run(() => {

          this.dataArray = data;
          console.log(data); // When in Component B, this is still firing in Dev Tools and I can see the new data being pushed.
        });
      }
    );
  }

}

组件A HTML

<ul *ngFor="let data of dataArray">
    {{ data }}
</ul>
<br/>

数据服务

export class DataService {

  private data: string[] = new Array<string>();
  private _dataSource = new Subject<string[]>();

  data$ = this._dataSource.asObservable();


  constructor(public electronService: ElectronService) {

    this.intitalizeIPCs();
  }


  intitalizeIPCs() {

    this.electronService.ipcRenderer.on('receive-data', (event, arg) => {
      console.log('received data');
      this.data = arg;
      this._dataSource.next(this.data);
    });
  }

App.component.html

<app-nav></app-nav>
<div class="content">
    <router-outlet></router-outlet>
</div>

编辑-带代码的解决方案

可接受的答案如下。正确的实现是通过使用异步管道。切换到异步管道后,我仍然遇到一个问题,即如果服务中的数据发生更改,则组件必须先重新导航才能看到更改。通过将其封装在NgZone中解决了该问题。下面的工作代码:

服务:

import { Injectable, NgZone } from '@angular/core';
import { ElectronService } from '../providers/electron.service';
import { Observable, BehaviorSubject } from 'rxjs';

@Injectable({
  providedIn: 'root'
})

export class DataService {

  private _data: BehaviorSubject<Array<string>> = new BehaviorSubject([]);
  public readonly data: Observable<Array<string>> = this._data.asObservable(); // Access this directly using async pipe.

  constructor(public electronService: ElectronService, private zone: NgZone) {

    this.intitalizeIPCs();
  }

  intitalizeIPCs() {
    this.electronService.ipcRenderer.on('receive-data', (event, arg) => {
      this.zone.run(() => {
        this._data.next( arg );
      });
    });
  }
}

组件:

import { Component, OnInit, ChangeDetectionStrategy } from '@angular/core';
import { DataService } from '../../services/metar.service';

@Component({
  selector: 'app-example',
  templateUrl: './example.component.html',
  styleUrls: ['./example.component.scss'],
  changeDetection: ChangeDetectionStrategy.Default
})
export class ExampleComponent implements OnInit {

  constructor(private _dataService: DataService) { }

  ngOnInit() {
  }


}

HTML

<ul *ngFor="let metar of _metarService.metars | async">
    {{ metar }}
</ul>

1 个答案:

答案 0 :(得分:1)

我强烈建议您使用async管道而不是订阅流。您遇到的不是故障的组件,而是内存泄漏。

当您订阅data$时,该订阅将保留在内存中,直到该订阅被取消为止(在您的情况下永远不会发生)。因此,组件A的实例也需要保留在内存中。

问题在于,更改到组件B的路由会使Angular放弃组件A的实例。因此Angular不再与其连接。从其观点来看,该组件不再存在。当您将路由切换回组件A时,Angular将创建一个新实例,它以['test1', 'test2']开头。