Here is the stackblitz code ,当使用 service.ts
文件进行 API 调用时,我从子组件发出事件。
我的child.comp.ts
import { Component, Output,EventEmitter } from '@angular/core';
import {Service} from './service';
@Component({
selector: 'child',
template: `Child data: {{data}}`
})
export class ChildComponent {
@Output() change = new EventEmitter();
data: string;
constructor(private svc: Service){}
ngOnInit(){
this.change.emit(true);
this.svc.getMsg()
.subscribe( data =>{
this.data = data;
this.change.emit(false);
})
}
}
我的app.comp.ts
import { Component ,ChangeDetectorRef} from '@angular/core';
import {Service} from './service';
@Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: [ './app.component.css' ]
})
export class AppComponent {
name = 'Angular 6';
show= false;
constructor(svc: Service,private crd: ChangeDetectorRef){}
showData(event){
this.show = event;
// this.crd.detectChanges(); // this stops the error
}
}
如您所见,添加 this.crd.detectChanges();
通过让 angular
知道这是需要另一个更改检测的部分来停止错误。
但是,I came across this answer on SO这个错误基本上代表了BAD 设计。并且使用 detectChanges()
似乎更像是一种修复,因为我必须明确地编写它。
谁能帮我做一个GOOD 设计,让我不必在生命周期中值会发生变化的地方显式地编写 detectChanges()
。
最佳答案
因此,我研究了实现您所写内容的最佳方法。 I asked the same question to Max .我可以得出的结论是
Angular follows Unidirectional flow of data, as you can read over here
在您的情况下,您基本上是在 CD 中间更改 show
的值。现在发生的情况是,当 CD 在 DEV 模式下第二次触发时,它发现您使用 EventEmitter
更改了子组件的父数据。这与 Angular 的单向流 相矛盾。您的情况可能的解决方案,
使用
this.crd.detectChanges()
让 Angular 明确地知道您已经更改了值,因此 Angular 会很友好地再次运行 CD 不会抛出任何错误或者,在子项本身中实现
show
行为,而不是违背父级 -> 子级的流程。
关于angular - ExpressionChangedAfterItHasBeenCheckedError : when Event emitted from Child Component,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50784492/