Angular 2 - 模型更改后视图未更新
Angular 2 - 模型更改后视图未更新
我有一个简单的组件,每隔几秒调用一次REST api并接收一些JSON数据。通过我的日志语句和网络流量,我可以看到返回的JSON数据正在改变,我的模型正在更新,但是视图没有改变。
我的组件如下:
import {Component, OnInit} from 'angular2/core'; import {RecentDetectionService} from '../services/recentdetection.service'; import {RecentDetection} from '../model/recentdetection'; import {Observable} from 'rxjs/Rx'; @Component({ selector: 'recent-detections', templateUrl: '/app/components/recentdetection.template.html', providers: [RecentDetectionService] }) export class RecentDetectionComponent implements OnInit { recentDetections: Array; constructor(private recentDetectionService: RecentDetectionService) { this.recentDetections = new Array(); } getRecentDetections(): void { this.recentDetectionService.getJsonFromApi() .subscribe(recent => { this.recentDetections = recent; console.log(this.recentDetections[0].macAddress) }); } ngOnInit() { this.getRecentDetections(); let timer = Observable.timer(2000, 5000); timer.subscribe(() => this.getRecentDetections()); } }
而我的视图如下:
Recently detected
Recently detected devices
Id | Vendor | Time | Mac |
---|---|---|---|
{{detected.broadcastId}} | {{detected.vendor}} | {{detected.timeStamp | date:'yyyy-MM-dd HH:mm:ss'}} | {{detected.macAddress}} |
通过console.log(this.recentDetections[0].macAddress)
的结果,我可以看到recentDetections对象正在更新,但视图中的表格除非重新加载页面,否则永远不会改变。
我正在努力找到我到底做错了什么。 有人可以帮忙吗?
这原本是@Mark Rajcok在评论中的一个答案, 但是我想把它放在这里作为一个已经测试并作为使用ChangeDetectorRef 的解决方案, 我认为这是一个不错的观点:
另一个选择是注入
ChangeDetectorRef
并调用cdRef.detectChanges()
而不是zone.run()
。这可能更有效率,因为它不会像zone.run()
一样在整个组件树上运行变更检测。- Mark Rajcok
所以代码必须像这样:
import {Component, OnInit, ChangeDetectorRef} from 'angular2/core'; export class RecentDetectionComponent implements OnInit { recentDetections: Array; constructor(private cdRef: ChangeDetectorRef, // <== added private recentDetectionService: RecentDetectionService) { this.recentDetections = new Array (); } getRecentDetections(): void { this.recentDetectionService.getJsonFromApi() .subscribe(recent => { this.recentDetections = recent; console.log(this.recentDetections[0].macAddress); this.cdRef.detectChanges(); // <== added }); } ngOnInit() { this.getRecentDetections(); let timer = Observable.timer(2000, 5000); timer.subscribe(() => this.getRecentDetections()); } }
编辑:使用.detectChanges()
在subscibe
内可能会导致问题Attempt to use a destroyed view: detectChanges
要解决这个问题,你需要在销毁组件之前取消订阅
,所以完整的代码应该像这样:
import {Component, OnInit, ChangeDetectorRef, OnDestroy} from 'angular2/core'; export class RecentDetectionComponent implements OnInit, OnDestroy { recentDetections: Array; private timerObserver: Subscription; constructor(private cdRef: ChangeDetectorRef, // <== added private recentDetectionService: RecentDetectionService) { this.recentDetections = new Array (); } getRecentDetections(): void { this.recentDetectionService.getJsonFromApi() .subscribe(recent => { this.recentDetections = recent; console.log(this.recentDetections[0].macAddress); this.cdRef.detectChanges(); // <== added }); } ngOnInit() { this.getRecentDetections(); let timer = Observable.timer(2000, 5000); this.timerObserver = timer.subscribe(() => this.getRecentDetections()); } ngOnDestroy() { this.timerObserver.unsubscribe(); } }
可能是你的服务中的代码不小心跑出了Angular的zone,导致变更检测不能正常工作。应该采用以下方法处理:
import {Component, OnInit, NgZone} from 'angular2/core'; export class RecentDetectionComponent implements OnInit { recentDetections: Array; constructor(private zone:NgZone, // <== added private recentDetectionService: RecentDetectionService) { this.recentDetections = new Array (); } getRecentDetections(): void { this.recentDetectionService.getJsonFromApi() .subscribe(recent => { this.zone.run(() => { // <== added this.recentDetections = recent; console.log(this.recentDetections[0].macAddress) }); }); } ngOnInit() { this.getRecentDetections(); let timer = Observable.timer(2000, 5000); timer.subscribe(() => this.getRecentDetections()); } }
如需其他手动触发变更检测的方法,请查看在Angular中手动触发变更检测
其他触发变更检测的方法包括:
ChangeDetectorRef.detectChanges()
立即针对当前组件和它的子组件运行变更检测
ChangeDetectorRef.markForCheck()
在下次Angular运行变更检测时包括当前组件
ApplicationRef.tick()
对整个应用运行变更检测