typescript Angular 4:`ExpressionChangedAfterItHasBeenCheckedError:检查后表达式已更改
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/44070732/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Angular 4: `ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked
提问by Nicolas
Every EventEmiiter in my child module gives this error and I can't find a fix for this.
我的子模块中的每个 EventEmiiter 都会出现此错误,我找不到解决方法。
ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked. Previous value: 'true'. Current value: 'false'.
ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked. Previous value: 'true'. Current value: 'false'.
This is what triggers my EventEmitter:
这就是触发我的 EventEmitter 的原因:
ngOnChanges(changes: any) {
if (changes.groupingTabValid) {
if (changes.groupingTabValid.currentValue !== changes.groupingTabValid.previousValue) {
this.groupingTabValidChange.emit(this.groupingTabValid);
}
}
}
Here is my "main" componenent's HTML
这是我的“主要”组件的 HTML
<year-overview-grouping [definitionDetails]="definitionDetails"
[fixedData]="fixedData"
[showValidation]="showValidation"
[groupingTabValid]="groupingTabValid"
(groupingTabValidChange)="setValidators('groupingTab', $event)">
</year-overview-grouping>
Which calls this function
哪个调用这个函数
public setValidators(validator: string, e: boolean) {
switch (validator) {
case "groupingTab":
this.groupingTabValid = e;
break;
case "selectionTab":
this.selectionTabValid = e;
break;
}
if (this.groupingTabValid && this.selectionTabValid) {
this.valid = true;
} else {
this.valid = false;
}
}
1) In a a simple explanation, what's causing this error?
1)在一个简单的解释中,是什么导致了这个错误?
2) What steps can I take to solve this?
2)我可以采取什么步骤来解决这个问题?
回答by Draeken
Abide by the unidirectional data flow rule
遵守单向数据流规则
Try to postpone the call to emit for one tick with a setTimeout
尝试使用 setTimeout 推迟发出一个滴答声的调用
if (changes.groupingTabValid.currentValue !== changes.groupingTabValid.previousValue) {
setTimeout(() => this.groupingTabValidChange.emit(this.groupingTabValid), 0)
}
回答by Cengkuru Michael
Just import ChangeDetectionStrategy and then add this to your component
只需导入 ChangeDetectionStrategy,然后将其添加到您的组件中
@Component({
changeDetection: ChangeDetectionStrategy.OnPush,
selector: 'app-bla-bla-bla',
templateUrl: './xxxxx'
})
回答by Micha? Pietraszko
You can avoid using setTimeout
and tell Angular that changes are about to happen after initial check.
您可以避免使用setTimeout
并告诉 Angular 在初始检查后即将发生更改。
You can inject ChangeDetectorRef
into your component and use its markForCheck
method.
您可以注入ChangeDetectorRef
组件并使用其markForCheck
方法。
/* ... */
constructor(private cdr: ChangeDetectorRef) {}
/* ... */
if (changes.groupingTabValid.currentValue !== changes.groupingTabValid.previousValue {
this.cdr.markForCheck();
this.groupingTabValidChange.emit(this.groupingTabValid);
}
回答by Richard Matsen
I'm just starting to look at this exception type myself, so no expert, but presume that it's there to stop feedback loops.
我刚刚开始自己研究这种异常类型,所以不是专家,但假设它可以停止反馈循环。
I can't see any obvious reason why you want to send the value down to the child and back up to the parent, but presume the child applies some additional logic. To me, seems better to apply any additional logic in a service rather than a child component.
我看不出任何明显的原因,为什么您要将值向下发送给子级并返回给父级,但假设子级应用了一些额外的逻辑。对我来说,在服务而不是子组件中应用任何附加逻辑似乎更好。
I realize the plunker code doesn't have a loop, but the Angular mechanism seems rather simple - just re-checks values at the end of the cycle. Note, groupingTabValidin your question code does feedback directly.
我意识到 plunker 代码没有循环,但 Angular 机制似乎相当简单——只需在循环结束时重新检查值。请注意,问题代码中的groupingTabValid直接进行反馈。
Looking at the plunker code as given, structurally the change to age can be handled on the parent. The click event would be (click)=changeAge(age.value)
and the method (on parent) to handle it
查看给定的 plunker 代码,结构上可以在父级上处理年龄的更改。单击事件将是(click)=changeAge(age.value)
处理它的方法(在父级上)
changeAge(inputAge) {
this.newAge = inputAge;
this.person.age = inputAge;
}
Here's a fork of the plunker. Modified plunker
The child component still updates person.age, but no longer causes an error as the value is the same as set on the parent.
这是plunker的一个叉子。修改plunker
子组件仍然更新person.age,但不再报错,因为值与父组件设置的相同。