ngIf 表达式在检查后发生了变化
Posted
技术标签:
【中文标题】ngIf 表达式在检查后发生了变化【英文标题】:ngIf Expression has changed after it was checked 【发布时间】:2019-01-05 21:37:34 【问题描述】:我将用一个简化的例子来解释我的问题,因为我的代码很长。
当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;
【问题讨论】:
您能否添加负责设置isFetching
和isDownloading
的代码?
ngIf - Expression has changed after it was checked的可能重复
@user184994,我已经添加了您要求的代码。
This comment 在官方仓库中可能会有所帮助
您可能希望将该代码移出构造函数并移入ngOnInit
【参考方案1】:
您可能需要考虑另一种模式,使用 observables,它可以简化您的代码(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
-like 标志的需要。
关于你的代码:
firebase.database().ref('/users/' + this.userId).once('value').then(function(snapshot)
this.username = (snapshot.val() && snapshot.val().username) || 'Anonymous';
this.isFetching = false;
);
我根本不知道这将如何工作,因为回调函数 (function(snapshot)
) 中的 this
可能是未定义的,给你一个运行时错误。
我不是 Angular 内部的专家,但我怀疑导致您报告的错误的原因是以下事件序列:
-
组件被实例化,构造函数运行。
Firebase 查询开始。
调用
ngOnInit
并检查检测到变化的变量。 isFetching
在这一点上仍然成立。
Angular 做更多的工作来构建视图和你有什么。
与此同时,Firebase 查询完成,并且“isFetching”设置为 false。
在完成这一轮渲染之前,Angular 会再检查一次(它在测试模式下执行此操作),以确保没有任何意外更改。但它有!
正如评论中提到的,这整个问题是由将 firebase 查询逻辑放在构造函数中引起的。构造函数应严格限于基本初始化。它们不应该包含业务逻辑,并且绝对不应该包含异步的东西。
【讨论】:
以上是关于ngIf 表达式在检查后发生了变化的主要内容,如果未能解决你的问题,请参考以下文章
使用反应式表单在 Angular 中检查后,表达式发生了变化