angular2中的更改检测是否始终在根组件中启动?

时间:2016-04-08 00:58:21

标签: javascript typescript angular

考虑Angular2

中的以下组件树结构
     A
  B     C
D  E   F  G

如果G通过点击C发出了一个事件而C没有进一步发生该事件

html

<div (click)="update($event)"></div>

component

@Output() myOutputName = new EventEmitter();

update(event) {
    this.myOutputName.emit('some vlaue'); 
}

更改检测是否在从A开始的所有节点中运行,或者确实更改了C上的检测开始并仅影响FG

1 个答案:

答案 0 :(得分:2)

  

更改检测是否运行

这取决于。默认情况下,更改检测将在每个异步事件(以及由Zone.js进行猴子修补的每个异步事件)之后运行,从组件树的顶部/根开始,然后以深度优先顺序访问每个节点一次。所以A-B-D-E-C-F-G(不是A-B-C-D-E-F-G,它将是广度优先的顺序)。

但是,如果您对组件G禁用了更改检测(请参阅detach()),则单击处理程序运行后将不会运行更改检测。

  

更改检测是否在所有节点中运行

再次,这取决于。默认情况下,是,检查每个节点。

但是,组件可以从更改检测器树中分离(正如我刚才提到的),或者可以将它们配置为使用OnPush更改检测策略。如果某个组件使用OnPush,则只会检查是否标记了&#34;&#34;通过以下条件/事件之一进行检查:

  • 其中一个输入属性已更改
  • 该组件触发了一个事件(即,其模板中的某些事件绑定触发了一个事件)
  • 一个observable触发了一个事件,并且该observable在视图/模板中与| async一起使用
  • 该组件被标记为&#34;通过调用markForCheck()进行检查 - 这可以在组件逻辑中调用,或者在某些后代逻辑中调用(更多关于此内容)

如果OnPush组件未标记为&#34;,则不会检查该组件的更改,也不会检查其任何后代(无论改变他们正在使用的检测策略)。因此,如果组件G使用默认的更改检测策略,但父组件C使用OnPush,如果C未标记为要检查,则G也不会被选中。

您可以使用OnPush手动标记markForCheck()组件。此方法还会将其所有祖先标记为根组件。它必须这样做,因为变化检测始终从根...开始...并且为了使变化检测返回到标记为&#34;组件,Angular必须确保链/树上的任何其他OnPush组件也被标记。否则,更改检测将永远不会使其返回到此组件。

对于仅使用输入属性的叶节点/组件,

OnPush通常是一个不错的选择(即,他们不会从服务中获取数据。)

默认情况下,更改检测始终从根组件开始。但是,如果您手动调用detectChanges(),它将只检查当前组件及其后代。