Does Angular use DOM diffing or must it "re-render" every list item? Does Angular use DOM diffing or must it "re-render" every list item? reactjs reactjs

Does Angular use DOM diffing or must it "re-render" every list item?


There is quite a bit of confusion regarding this topic, mostly because it's not a simplistic "angular re-renders everything" type answer.

The basis of angular data binding (in 1.x releases) surrounds around the concept of a $digest loop and $scope. $scope is a special object which "self tracks" it's properties, and creates a JavaScript event listener for each property, using the method $scope.$watch(). These listeners monitor changes to the changeable input elements in HTML, and to the $scope properties.

Whenever any JavaScript listener fires, the $digest loop cycles through every item under $watch and updates the values appropriately. You also can call $scope.$apply() to manually execute a $digest loop. This loop can execute multiple times, as changes to one value can affect another value under $watch which triggers another $digest. The $digest loop does have an iteration cap to ensure it stops on circular references, however.

The rub comes in when you are dealing with arrays of objects, and the special directive ng-repeat. By default, the $watch() function only checks object reference equality. Within each $digest, AngularJS will check to see if the new and old values are the same "physical" object, and will only invoke its handler if you actually change the underlying object reference.

To counter this, ng-repeat creates it's own unique scope. This allows for a unique $watch for every element in the array. The challenge here is that if the array itself changes, then this unique scope is regenerated, along with all the $watch elements. Pushing, Popping, Splicing an array can create many $watch values.

Angular provides a few ways to deal with this issue.

The new Bind Once syntax added in 1.3 allows for Listeners which only exist until the expression is evaluated. ng-repeat="element in ::elements" Will iterate through the array, populate the DOM, then destroy the Event Listener. This is ideal for situations where the DOM element does not change once evaluated.

It is also possible to aggressively track elements, using track by. ng-repeat="element in elements track by $id" will create a $watch on the unique $id value, rather than the element's position in the array. This allows for more stable $watch propagation, and is ideal in cases where the value of the element may change.

As to why the changes you made in the console were not lost: Firstly, changes in the developer console are not going to trigger any Event Listeners. Secondly, the specific DOM element you changed would only be modified if the $watch detected a change. This is not really a 'Diff' of the HTML, however; Angular isn't "watching the HTML", it is "watching the data", so to speak.