Mar*_*rgh 4 data-binding angular2-changedetection angular
我不太明白为什么我需要在下面的代码中添加 markForCheck() 以使更改可见。为什么我的@Input() 没有触发变化检测?
我正在将我的项目重构为 OnPush。这两个组件都启用了 OnPush。据我了解,当启用此功能并且 Input() 更改(例如messages)时,更改检测将被触发。
在下面的代码中,我通过graphqlService. 当我收到调用时,我会对传入的数据进行一些解析,然后将其设置为informationMessages属性,该属性cv-messages通过其messages属性绑定到子组件。
结果是该ngOnChanges函数仅在informationMessages属性初始化时被调用一次。但不是当最终解析的数据设置为它时。
如果我添加 markForCheck() 它工作正常。
考虑这个父组件,它有一个这样的模板:
<cv-messages [messages]="informationMessages"></cv-messages>
Run Code Online (Sandbox Code Playgroud)
以及带有这段代码的打字稿文件:
informationMessages: InformationMessageType[] = [];
ngOnInit() {
this.graphqlService.loadInformationMessages().subscribe(data => {
const informationMessages: InformationMessageType[] = data;
.... // parsing stuff
this.informationMessages = informationMessages;
// add markForCheck() here
});
}
Run Code Online (Sandbox Code Playgroud)
消息组件有一个 ngOnChanges 函数,如下所示:
ngOnChanges(changes) {
console.log(this.constructor.name ' CHANGE:', changes);
}
Run Code Online (Sandbox Code Playgroud)
更新:
您可以在以下答案的评论中找到解决方案。基本上,当异步更改时不会触发更改检测@Input()。所以在这种情况下,我们需要添加一个markForCheck()来强制更改检测。
当视图使用 OnPush (checkOnce) 更改检测策略时,将视图显式标记为已更改,以便可以再次检查。
当视图中的输入更改或事件触发时,组件通常被标记为脏(需要重新渲染)。调用此方法以确保即使未发生这些触发器也会检查组件。
因此需要使用此方法将组件标记为脏以重新渲染。
更新:
有两种类型ChangeDetectionStrategy:
OnPush: 0 使用 CheckOnce 策略,这意味着自动更改检测被停用,直到通过将策略设置为默认 (CheckAlways) 重新激活。仍然可以显式调用更改检测。此策略适用于所有子指令,不能被覆盖。
默认值:1 使用默认的 CheckAlways 策略,其中更改检测是自动的,直到明确停用。
所以,当你使用OnPush则自动变化检测被停用,并有必要将其标记为更改,以便它可以再次检查视图。