How does data binding work in AngularJS?

I have not found a detailed description on this site .

  1. How does AngularJS track changes in model properties without setters and getters?
  2. How does AngularJS know that I have changed, for example, the following variable and displays this change in the view?

    $scope.myobject = { myproperty : 'old value' }; myobject.myproperty = 'new value'; 
  • Are you sure of the truth of the second statement? If there is no link to myobject in $ scope or $ rootScope, then AngularJS does not recognize anything. - sba
  • why wait? if you know the answer, you can give it yourself and get a well-deserved reward in the form of a turnip , or translate the answer, this is also not prohibited - Bald
  • We ask for an answer :) It is interesting. - user207618
  • I have not found a detailed description on this site. - and there it is, just a few large sections - Grundy
  • There are excellent answers in English stackover. - as an option, you can translate them, indicating the source. Transfers are supported - Grundy

1 answer 1

Angular remembers the value and compares it with the previous value. If there is a change in value, then it triggers a change event.

1. Observers

Angular maintains a simple list of watсhers (observers), which is contained in $ scope objects. If you check any $ scope in your application, you will notice in it the $$ watchers field.

Each watcher (observer) is an object that consists of the following:

  1. An expression that checks watcher. This may be the name of an object attribute or something more complex;
  2. Last known expression value. This value can be compared with the value of the current calculated expression. If the values ​​are different, the watcher will call the function (see below), and also $ scope will be marked as dirty.
  3. The function that will be executed if the observed expression has changed.

2. Ways to create observers

There are various ways to define observers:

  1. You can explicitly define watcher as the $ scope attribute:

     $scope.$watch('person.username', validateUnique); 

    Where validateUnique is the function that will be called if the value of the person.username field person.username .

  2. You can put your expression in braces in a pattern (watcher will be created for the current $ scope automatically):

     <p>username: {{person.username}}</p> 
  3. You can define a directive such as ng-model, ng-repeat:

     <input ng-model="person.username" /> 

3. The $ digest cycle

When you start your angular application, the $ digest loop starts.

In the $ digest loop, two more loops are performed. One of the cycles processes the $ evalAsync queue, the second one is the $ watch list. The $ digest loop runs until the value of your expression is synchronized. This means that $ evalAsync is empty, and there will be no changes in $ watch.

The $ digest cycle is a detour of $ scope and all its child visibility areas. For each $ scope, its $$ watchers array will be scrolled and its expression will be evaluated for each element (has it changed). If the new value of the expression differs from the last known one, then the observer function is called. This function can recompile the DOM part, rewrite the value in $ scope, trigger an AJAX request, etc.

4. What happens if watcher works

If watcher works, then the application knows that something has changed and $ scope is marked as dirty.

Observer functions can change other variables of the current or parent $ scope, so the $ digest loop will be called again. This ensures that all $ scope will eventually be synchronized (the values ​​of all the monitored expressions will be the same as in the previous iteration of the $ digest loop). But this behavior of the $ digest loop would cause looping, so by default it can be called up to 10 times in a row, until all $ scope are marked clean. If this limit is exceeded, we will see such an error in the console:

 10 $digest() iterations reached. Aborting! 

5. Performance.

As you can see, with any changes in the application, in order to understand how to react, angular will check every single watcher in the entire $ scope hierarchy.

From the point of view of the developer, this is very productive, since there is no need to think about how to track changes in expressions and display them in a template. If the expression has changed, then Angular will simply replace it.

From the point of view of the machine, this is very inefficient and it will slow down your application.

From a person’s point of view:

  • Slowly - Everything that happens faster than 50ms is unnoticeable to humans. Thus, 50ms can be considered as "instantly."

  • Limited - You can't really show more than about 2000 pieces of information to a person on one page. If you have more information on the page than this value, then in fact this is a bad UI, and users cannot handle it anyway.

So the real question is: How many comparisons can you do in a browser for 50ms? This is a difficult question, as many factors come into play. Here is a test that creates 10,000 observers. In a modern browser, it takes less than 6ms. In Internet Explorer 8 - about 40ms. As you can see, this is not a problem, even for older browsers. There is one caveat: Comparisons should be simple to fit into the time limit. Unfortunately, it’s too easy to add slow comparisons to your application, so it’s very easy to build a slow application when you don’t know exactly what you are doing.

6. One time binding

Greater productivity can be achieved through the use of one-time binding. Such expressions will be recorded in the template of your application once and will not be tracked in the $ digest loop, respectively, we get a performance boost and can allocate a place in the $ digest loop for more important expressions. If you know that some elements of your application are created in your template once and no longer change, then a one-time binding is what you need. A simple example of a one-time binding:

 <h1>{{ ::title }}</h1> 


Source: https://stackoverflow.com/questions/9682092/how-does-data-binding-work-in-angularjs

  • one-time binding is not one-way, but rather one-time binding - Grundy
  • it is better to throw out the "performance" item altogether, or narrow it down to one sentence: many observers are bad. - Grundy
  • in general, an attempt was made to answer all at once in one place, in the end, on the tops and half to the end. It is better to specify both the question itself and the answer itself. Specifically, it was worth more attention to the observers and their work. At least there is not enough description of $watchCollection , there is no description of what these functions return and how they work at all - Grundy
  • With regard to performance, everything was taken from here . I believe that it is important to know when it comes to angular binding. - Max
  • Since it was a translation, as I understand it, not one answer, it was worth pointing out the links to the source. In any case, if you compare your answer with the fact that the links, you have it turned out wider. And this is not very good. - Grundy