我有一个包含几个组件的应用程序,每个组件异步显示不同的数据。我正在使用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>
答案 0 :(得分:1)
我强烈建议您使用async
管道而不是订阅流。您遇到的不是故障的组件,而是内存泄漏。
当您订阅data$
时,该订阅将保留在内存中,直到该订阅被取消为止(在您的情况下永远不会发生)。因此,组件A的实例也需要保留在内存中。
问题在于,更改到组件B的路由会使Angular放弃组件A的实例。因此Angular不再与其连接。从其观点来看,该组件不再存在。当您将路由切换回组件A时,Angular将创建一个新实例,它以['test1', 'test2']
开头。