Reputation: 2343
Consider the following component tree structure in Angular2
A
B C
D E F G
If G
emits an event via click to C
and C
does not further that event
html
<div (click)="update($event)"></div>
component
@Output() myOutputName = new EventEmitter();
update(event) {
this.myOutputName.emit('some vlaue');
}
Does the Change detection runs in all nodes starting from A
or does change detection start on C
and effect only F
and G
?
Upvotes: 4
Views: 1606
Reputation: 364717
Does the Change detection runs
It depends. By default, change detection will run after every asynchronous event (well, every asynchronous event that was monkey-patched by Zone.js), starting from the top/root of the component tree and then visiting each node once, in depth-first order. So A-B-D-E-C-F-G (not A-B-C-D-E-F-G, which would be breadth-first order).
However, if you have change detection disabled for component G (see detach()
), then change detection will not run after the click handler runs.
Does the Change detection runs in all nodes
Again, it depends. By default yes, every node is checked.
However, components can be detached from the change detector tree (as I just mentioned), or they can be configured to use the OnPush
change detection strategy. If a component uses OnPush
, it will only be checked if gets "marked" for check, by one of the following conditions/events:
| async
in the view/templatemarkForCheck()
– this could have been called in the component logic, or in some descendant logic (more about this below)If the OnPush
component is not "marked", that component will not be checked for changed, nor will any of its descendants be checked (regardless of the change detection strategy they are using). So, if component G uses the default change detection strategy, but parent component C uses OnPush
, if C is not marked for check, G won't be checked either.
You can manually mark an OnPush
component using markForCheck()
. This method will also mark all of its ancestors up to the root component. It must do this because change detection always starts from the root... and in order for change detection to make it back down to the "marked" component, Angular has to make sure that any other OnPush
components up the chain/tree are also marked. Otherwise, change detection will never make it back down to this component.
OnPush
is often a good choice for leaf nodes/components that only use input properties (i.e., they don't get their data from services.)
By default, change detection always starts from the root component. However, if you manually call detectChanges()
, it will only check the current component and its descendants.
Upvotes: 2
Reputation: 55443
YES, CHANGE DETECTION ALWAYS STARTS FROM ROOT COMPONENT
slide - http://pascalprecht.github.io/slides/angular-2-change-detection-explained/#/54
Data always flows from top to bottom, is because change detection is also always performed from top to bottom for every single component, every single time, starting from the root component
So if G
emits an event,
change detection will start from root component,
A
(change detection in A)
B
C
(change detection in B,C)
D
E
F
G
(change detection in D,E,F,G)
Keep in mind, there are ways to deal with change detection.
But Yes BY DEFAULT, change detection starts from Root
For further reference,
article
1) http://blog.thoughtram.io/angular/2016/02/22/angular-2-change-detection-explained.html
2) http://victorsavkin.com/post/110170125256/change-detection-in-angular-2
Upvotes: 2