阅读Zone.JS并更改检测过程,在源代码中,Zone.JS通过传播对所有组件的检查来通知Angular它从上到下运行第一个组件的变化,但在我的测试中,我有不同的行为 .
检查我的样本:
http://plnkr.co/edit/QPHBQ7cYg9JFZr2oVnGZ?p=preview
该示例具有以下体系结构:
<app-component>
<child-component>
<grand-child-component>
它们彼此嵌套,没有@Input属性,并且它们都是OnPush,它们在视图中显示一个简单的值,如:
视图:
{{getComponentValue}}
打字稿
value = "app component";
get getComponentValue() { // <-- ES6 get to log when Angular check
console.log('change detection checking here in component app-component')
return this.value;
}
您可以在示例中查看此代码 .
启动应用程序后,我们可以看到日志:
check component app
check component child
check component grand child
很酷,但是,现在让我们想象一下,如果盛大的孩子会引发一个事件?
改变大孩子的观点
<button (click)="undefined"> {{getComponentValue}} </button>
<!-- (click)="undefined" cria um inscrito no evento. -->
我们有日志:
check component app
check component child
check component grand child
我期望:当我点击爷爷按钮时,事件将从app-component开始,但由于所有这些都是OnPush,因此事件不会因为没有@Input被更改而进入盛大孩子,我必须手动调用markforcheck或detectchanges,但上面的代码看起来像我调用了markforcheck .
我在grand-child组件中使用ts中的observable调用了settimeout,interval和events,并且没有调用更改(检查grand-component ts),只在视图中(单击)调用check ...
您可以使用以下命令进行验证:在子项或app组件中,您可以添加增加值的setInterval并且您可以在视图中检查,只有当孙子触发您的祖先的(点击)值时才能实现更新了!
我意识到:settimeout,interval或者在组件的ts内具有observable的事件以及当组件是OnPush时事件在app组件中启动但它们没有被“强制传播”,因为@Input没有变化,但是当我们在视图中添加事件,比如(点击)某些通过模拟markForCheck强制它们的方式,实际发生了什么?
当我们在视图中添加一个事件时,引擎盖下的Angular会强制执行markForCheck();到组件?因为这似乎发生了什么 .
1 回答
是的,这是设计的:内部绑定事件triggers markForCheck
也可以看看