An overview of the

This is a theoretical article, Angular change detection is the soul of the framework, if we understand this content, optimize applications, solve performance problems, and better understand Angular. This article covers the following topics: Angular \color{#13c078}{Angular}Angular change detection policy \color{#13c078}{change detection policy}Angular change detection policy, Change detection method \color{#13c078}{change detection method} Angular \color{#13c078}{Angular}Angular Color {#13c078}{ChangeDetectorRef {ChangeDetectorRef}ChangeDetectorRef {ChangeDetectorRef}

What behavior causes Angular change detection?

  • DOM events: click, submit…
  • XHR: obtains data from the server
  • Timers: setTimeout and setInterval

As shown above, we can see that whenever an asynchronous operation occurs, our application state can change. This is when Angular views need to be updated and change detected.

Who notifies Angular for change detection?

Angular has its own zone, the common ngZone, and the Angular source code has something called ApplicationRef that listens for the onTurnDone event of the ngZone. As soon as this event occurs, it executes the tick()\color{#13c078}{tick()}tick() function. This function checks for changes and the DOM is updated. Color {#13c078}{color{#13c078}{color{#13c078}}{color{#13c078}}

How is change detection performed?

In Angular, each component has its own change detector. Because we can individually control when and how change checks are performed for each component, since each component has its own change checker, color{#13c078}{change checker} change checker, and an Angular application contains a component tree, Color {#13c078}{change Detector tree}{change Detector tree} The tree can also be thought of as a directed graph, in which data always flows from top to bottom (one-way data flow). Each view (component) has a state, which is important because Angular decides whether to run or skip dirty value detection on the view and all its children based on its values (FirstCheck, ChecksEnabled, Errored, Destoryed). If ChecksEnabled is false or the view is in the state of Errored or Destroyed, change detection will skip the view and its subviews.

There are two strategies for Angular change detection, One is the ChangeDetectionStrategy. The Default strategy \ color # 13 c078} {{ChangeDetectionStrategy. The Default strategy} ChangeDetectionStrategy. The Default strategy, Another is ChangeDetectionStrategy onPush \ color # 13 c078} {{ChangeDetectionStrategy. OnPush} ChangeDetectionStrategy. OnPush strategy, Next, we will elaborate on ~

Angular’s Default policy

The default policy, which is often referred to as dirty checking, is to change fromThe root componenttoAll child componentsCheck (depth-first traversal)

Angular’s onPush policy

As with default change detection, Angular must detect all components every time, but it would be more efficient if Angular could only detect changes in the state of the application. We usually do this in both directions for more efficient and intelligent change detection.

  • Use immutable objects (reduce contrast of object properties)

Immutable object ensures that the object is immutable, which means that if we users immutable objects, try to change the object at the same time, we always get a new reference, if our requirement is as long as the address change to change detection, so that we do not need to compare the attributes of objects

  • Reduce the number of detection components

If we use an onPush strategy in a component, change detection is disabled after the first check, and Angular skips change checking for the entire subtree only if the Input property (@input) hasn’t changed. This change detection only applies to the current component and its children, and its neighboring siblings are not affected.

The usage method is as follows:

@Component({
  selector: 'app-test'.templateUrl: './test.component.html'.styleUrls: ['./test.component.scss'].changeDetection: ChangeDetectionStrategy.OnPush, // Use Angular's onPush policy
})
Copy the code

Under the onPush policy, what conditions can cause component change detection?

  1. Color {#13c078}{reference to Input data (@Input)} the component does change detection only if the reference to Input data (@Input) changes.
  2. Color {#13c078}{DOM event trigger} Component change detection only when DOM event trigger, other asynchronous event change data will not trigger change detection. (And change detection can still occur even if the event is an empty function or operates on something other than the @input attribute.)
  3. Manual trigger \color{#13c078}{manual trigger} Manual trigger change detection

How do YOU manually trigger change detection?

Change detection can be manipulated manually by referring to ChangeDetectorRef\color{#13c078}{ChangeDetectorRef} ChangeDetectorRef. We can get this object from a component by dependency injection:

constructor(
   private changeRef: ChangeDetectorRef
){}
Copy the code

This change detection object provides the methods shown below

abstract class ChangeDetectorRef {

abstract markForCheck() : void 

abstract detectChanges() : void

abstract detach() : void

abstract reattach() : void 

abstract checkNoChanges() : void

}
Copy the code
markForCheck()

Color {#13c078}{color{#13c078}{color{#13c078}{color{#13c078}{color{#13c078}{color{#13c078}{color{#13c078}}{color{#13c078}{color{#13c078}} Unless manually invoking this method, in the program to use this. ChangeRef. MarkForCheck () can cause a \ color # 13 c078} {{can only cause a} can only cause a change detection, if want to want to perform multiple times, you will need to run this sentence many times. The specific execution process is as follows:

detectChanges()

Color {#13c078}{only run change detection} only runs change detection once for the current view and its children. Application scenario: Angular knows that data is being updated and needs change detection.

detach()

Color {#13c078}{separate change detector} separate change detector from the change detection tree. The change detector of this component will no longer perform change detection, and its sub-components will not perform change detection. Unless the reattach() method is manually called

reattach()

Color {#13c078}{add separate change detector} add separate change detector, so that this component and its children can perform change detection. But if the parent of the current component is not change detection enabled \color{#13c078}{change detection is not enabled} change detection (dirty check) is not enabled \color{#13c078}{no effect} does not work.

Using async pipe

When the parent component of the input attribute is used observables, so in addition to using this. ChangeRef. MarkForCheck () to change detection, we can also use async in child components pipe, issued a new value, Asynchronous pipeline components will be marked as we need to check change (is also called the enclosing changeRef. MarkForCheck ())

<p>{{addCount | async}}</p>
Copy the code

ChangeDetectorRef comparison of miscible methods

MarkForCheck () vs. detectChanges()?
  • MarkForCheck () :

Instead of actually triggering a check, the root component is marked as requiring a check, which is basically only used when Angular’s check policy is set to OnPush, and which extends from the current component up to the root component

  • DetectChanges () :

Angular’s change detection method is used when data is updated but views are not. It is one of the methods used to manually trigger change detection. Of course, the microtask timer will also trigger change detection (3) for the current component and all its sub-components (4) which can be used with Detach for partial updates

Reattach () vs. detectChanges()?
  • DetectChanges ()

It only causes the change detection to be executed manually once

  • reattach()

If the view is added back, change detection will continue to change according to the changes in the business data, which is equivalent to completely restoring the original change detection

To better understand the difference between the two methods, use an example:

Example:

When num is 5, because detach() is used, the view is not doing change detection. When we call RecoveryDetection() and reattach(), the page shows incremental data recovery. If detectChanges() is implemented in this method, The page data will only be added once, and will not be updated

conclusion

If you want to really understand Angular change detection, you must write a demo to verify your assumptions. Otherwise, as I did before, you can’t understand the theory. It is also very easy to confuse the ChangeDetectorRef properties