ng如果表达式在检查后已更改

时间:2018-07-29 12:31:55

标签: angular typescript expression ngif

由于我的代码很长,我将用一个简化的示例来说明我的问题。

我想在isFetchingisDownloading之一为真时显示特定的div。

<div *ngIf="(isFetching || isDownloading)">
  My div element is here
</div>

在我的程序开始时,它们都是正确的,因此应该显示div。在上方的div下方,我将isFetching更改为false后在视图上显示了其他元素。 (从数据库中获取完成后,{isFetching更改为false。)在isFetching更改为false并呈现元素之后,这些元素的最后一个元素之后下载(这是一个图像),然后将isDownloading更改为false

isFetchingisDownloading均为假时,这是我要隐藏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;
}

1 个答案:

答案 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内部专家,但是我怀疑是什么导致您报告的错误是以下事件序列:

  1. 实例化组件并运行构造函数。
  2. Firebase查询开始。
  3. 调用
  4. ngOnInit并检查更改检测变量。 isFetching仍然是正确的。
  5. Angular在构建视图以及您所拥有的内容方面做了更多工作。
  6. 同时,Firebase查询完成,并且'isFetching`设置为false。
  7. 在完成这一轮渲染之前,Angular再检查一次(它在测试模式下进行),以确保未发生意外更改。但是它有!

整个问题是由于将Firebase查询逻辑放入构造函数中引起的,如注释中所述。构造函数应严格限于基本初始化。它们不应包含业务逻辑,并且绝对不应包含异步内容。