angular度2 – 查看模型更改后不更新

我有一个简单的组件每隔几秒调用一次REST API,并接收一些JSON数据。 我可以从我的日志语句和networkingstream量中看到正在返回的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<RecentDetection>; constructor(private recentDetectionService: RecentDetectionService) { this.recentDetections = new Array<RecentDetection>(); } 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()); } } 

我的观点如下所示:

 <div class="panel panel-default"> <!-- Default panel contents --> <div class="panel-heading"><h3>Recently detected</h3></div> <div class="panel-body"> <p>Recently detected devices</p> </div> <!-- Table --> <table class="table" style="table-layout: fixed; word-wrap: break-word;"> <thead> <tr> <th>Id</th> <th>Vendor</th> <th>Time</th> <th>Mac</th> </tr> </thead> <tbody > <tr *ngFor="#detected of recentDetections"> <td>{{detected.broadcastId}}</td> <td>{{detected.vendor}}</td> <td>{{detected.timeStamp | date:'yyyy-MM-dd HH:mm:ss'}}</td> <td>{{detected.macAddress}}</td> </tr> </tbody> </table> </div> 

我可以从console.log(this.recentDetections[0].macAddress)的结果中看到recentDetections对象正在被更新,但是视图中的表不会改变,除非我重新加载页面。

我很努力地看到我在这里做错了什么。 谁能帮忙?

可能是你的服务中的代码以某种方式脱离了Angulars区域。 这打破了变化检测。 这应该工作:

 import {Component, OnInit, NgZone} from 'angular2/core'; export class RecentDetectionComponent implements OnInit { recentDetections: Array<RecentDetection>; constructor(private zone:NgZone, // <== added private recentDetectionService: RecentDetectionService) { this.recentDetections = new Array<RecentDetection>(); } 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()); } } 

有关调用更改检测的其他方法,请参阅手动触发Angular2更改检测

调用变更检测的其他方法是

 ChangeDetectorRef.detectChanges() 

立即运行对当前组件的变化检测,这是孩子

 ChangeDetectorRef.markForCheck() 

在下一次Angular运行更改检测时包含当前组件

 ApplicationRef.tick() 

运行整个应用程序的变化检测

尝试使用@Input() recentDetections: Array<RecentDetection>;

编辑:为什么@Input()是重要的原因是因为你想要在打字稿/ javascript文件中的值视图(HTML)。 如果使用@Input()装饰器声明的值发生更改,视图将自动更新。 如果一个@Input()或者@Output()修饰器被改变了,一个ngOnChanges事件将会触发,并且这个视图将会用新的值来更新自己。 你可能会说@Input()会双向绑定这个值。

search在这个链接上的input:angular度更多信息

编辑:在学习了更多关于Angular 2开发之后,我想到做一个@Input()真的不是解决scheme,正如在评论中提到的,

@Input()仅适用于数据从组件外部进行数据绑定(父级绑定数据发生更改)而不是数据从组件内部的代码更改时更改的情况。

如果你看一下@Günter的答案,这是一个更准确和正确的解决scheme。 我仍然在这里保留这个答案,但请按照Günter的答案作为正确的答案。

它原本是在@Mark Rajcok的评论中的答案,但我想把它放在这里作为一个testing和使用ChangeDetectorRef作为解决scheme,我看到一个很好的一点在这里:

另一种方法是注入cdRef.detectChanges()并调用cdRef.detectChanges()而不是zone.run() 。 这可能会更有效,因为它不会像zone.run()那样在整个组件树上运行变更检测。 Mark Rajcok

所以代码一定是这样的:

 import {Component, OnInit, ChangeDetectorRef} from 'angular2/core'; export class RecentDetectionComponent implements OnInit { recentDetections: Array<RecentDetection>; constructor(private cdRef: ChangeDetectorRef, // <== added private recentDetectionService: RecentDetectionService) { this.recentDetections = new Array<RecentDetection>(); } 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()内使用.detectChanges()可能导致问题尝试使用销毁视图:detectChanges

要解决它,你需要在销毁组件之前unsubscribe ,所以完整的代码将如下所示:

 import {Component, OnInit, ChangeDetectorRef, OnDestroy} from 'angular2/core'; export class RecentDetectionComponent implements OnInit, OnDestroy { recentDetections: Array<RecentDetection>; private timerObserver: Subscription; constructor(private cdRef: ChangeDetectorRef, // <== added private recentDetectionService: RecentDetectionService) { this.recentDetections = new Array<RecentDetection>(); } 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(); } }