角度OnPush组件,当视图角度力markForCheck中的触发事件自动?

时间:2017-07-24 18:26:03

标签: angular angular2-changedetection

阅读Zone.JS并更改检测过程,在源代码中,Zone.JS通过传播对所有组件的检查来通知Angular有关更改它从上到下运行第一个组件,但在我的测试中,我有一个不同的行为。

检查我的样本:

http://plnkr.co/edit/QPHBQ7cYg9JFZr2oVnGZ?p=preview

该示例具有以下架构:

<app-component>
    <child-component>
        <grand-child-component>

它们彼此嵌套,没有@Input属性,并且它们都是OnPush,它们在视图中显示一个简单的值,如:

视图:

{{getComponentValue}}

typescript

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或者检测更改,但上面的代码看起来像是我调用了markforcheck。 / p>

我在grand-child组件的ts中调用了settimeout,interval和event with observables,并且没有调用更改(检查grand-component ts),只在视图中(单击)调用check ...

您可以使用以下命令进行验证:在子组件或app组件中,您可以添加增加值的setInterval 你可以查看视图,意识到只有当孙子触发你的祖先的(点击)值时才会更新!

我意识到:settimeout,interval或在组件的ts内具有可观察对象的事件以及组件为OnPush时 某些事件在应用程序组件中启动,但它们没有“强行传播”,因为@Input没有变化,但是当我们在视图中添加事件时,就像某些事件的(点击)一样 通过模拟markForCheck强制它们的方式,实际发生了什么?

当我们在视图中添加一个事件时,引擎盖下的Angular会强制执行markForCheck();到组件? 因为那似乎发生了。

1 个答案:

答案 0 :(得分:2)

是的,这是设计的:内部绑定事件triggers markForCheck

export function dispatchEvent(
    view: ViewData, nodeIndex: number, eventName: string, event: any): boolean {
  const nodeDef = view.def.nodes[nodeIndex];
  const startView =
      nodeDef.flags & NodeFlags.ComponentView ? asElementData(view, nodeIndex).componentView : view;
  markParentViewsForCheck(startView); // <== this line
  return Services.handleEvent(view, nodeIndex, eventName, event);
}

另见