由于我的代码很长,我将用一个简化的示例来说明我的问题。
我想在isFetching
或isDownloading
之一为真时显示特定的div。
<div *ngIf="(isFetching || isDownloading)">
My div element is here
</div>
在我的程序开始时,它们都是正确的,因此应该显示div。在上方的div下方,我将isFetching
更改为false
后在视图上显示了其他元素。 (从数据库中获取完成后,{isFetching
更改为false
。)在isFetching
更改为false
并呈现元素之后,这些元素的最后一个元素之后下载(这是一个图像),然后将isDownloading
更改为false
。
当isFetching
和isDownloading
均为假时,这是我要隐藏div元素的时候。
但是,我刚刚解释的代码给了我这个错误:
Expression has changed after it was checked. Previous value: 'ngIf: true'. Current value: 'ngIf: false'.
我似乎不明白为什么会出现此问题?我的逻辑有什么问题?如何在不出现此错误的情况下达到预期的结果?
编辑:
此代码在我的课程的构造函数中
firebase.database().ref('/users/' + this.userId).once('value').then(function(snapshot) {
this.username = (snapshot.val() && snapshot.val().username) || 'Anonymous';
this.isFetching = false;
});
将isFetching
更改为false
之后。我的.html中还有其他要呈现的元素。然后在加载这些元素的最后一个元素(是图像)(load)="latestElementLoaded()"
之后调用此代码。
latestElementLoaded(){
this.isDownloading = false;
}
答案 0 :(得分:1)
您可能想考虑使用可观察的替代模式,它可以简化代码(AngularFire值得研究):
this.data$ = this.angularFirestore.doc('some/path').valueChanges();
这使您的数据可观察到(这只是演示代码-检查实际语法)。将其放在ngOnInit
中,而不是构造函数中。不得与.once
或快照或其他样板文件搞混。
现在,您可以在模板中编写
<div *ngIf="data$ | async as data; else notFetched">
Data is {{data | json}}
<ng-template #notFetched>Data is not fetched yet..wait...</ng-template>
</div>
这完全不需要像isFetching
这样的标志。
关于您的代码:
firebase.database().ref('/users/' + this.userId).once('value').then(function(snapshot) {
this.username = (snapshot.val() && snapshot.val().username) || 'Anonymous';
this.isFetching = false;
});
我根本不知道它如何工作,因为回调函数(this
)中的function(snapshot)
可能是不确定的,从而给您带来运行时错误。
我不是Angular内部专家,但是我怀疑是什么导致您报告的错误是以下事件序列:
ngOnInit
并检查更改检测变量。 isFetching
仍然是正确的。整个问题是由于将Firebase查询逻辑放入构造函数中引起的,如注释中所述。构造函数应严格限于基本初始化。它们不应包含业务逻辑,并且绝对不应包含异步内容。