AngularJS $watch $digest $apply

Source: Internet
Author: User


A Brief introduction
ANGULARJS provides a cool feature called two-way data binding, a feature that greatly simplifies how we write code. Data binding means that when any data in the view changes, the change is automatically fed back to the scope data, meaning that the scope model is automatically updated. Similarly, when the scope model changes, the data in view is updated to the most recent value. So how does Angularjs do that? When you write down an expression such as {{AModel}}, Angularjs will set up a watcher on the scope model for you to update the view when the data is changed.
Two $watch
1. What is $watch
The $watch method on the $scope object assembles a dirty value check for each $digest call within the angular event loop, and angular always returns a $digest loop if changes are detected on the expression.
In other words, the $watch represents the monitoring of the data source, and when the data source changes, it triggers the callback function of the second parameter.
2. Use
The $watch function itself accepts two necessary parameters and an optional parameter:
$scope. $watch (' AModel ', function (NewValue, oldValue) {
Update the DOM with NewValue
},true);
The first argument: can be a property of a scope object, or a function, and each $digest call in the $digest loop will involve it. If it is a string, angular evaluates it in the context of the $scope.
Second argument: The Listener function as a callback, which is wise when the current value of the first parameter is not equal to the previous value.
The third parameter: True/false, which defaults to False, is used primarily for cases where the first argument is a reference type.
3. For example:
<body>
<input ng-model= ' name ' type= ' text '/>
<div>change Count: {{count}}</div>
<script>
Angular.module (' myApp ', [])
. Run ([' $rootScope ', function ($rootScope) {
$rootScope. Count = 0;
$rootScope. Name = ' HCC ';
$rootScope. $watch (' name ', function () {
$rootScope. count++;
})
}]);
</script>
</body>
Use $watch to monitor the name in the $rootscope and increase the Count property in $rootscope by 1 when it changes. Therefore, each time we make a modification to name, the count number shown below is incremented by 1.
However, in practice, we often do not just monitor an attribute of a primitive type, but may also monitor the collection. For primitive types, if we use an assignment operation, the original type variable is "really" copied one at a time, but for a reference type, when the assignment is made, it simply points to the reference type of the assigned variable. So if you want to monitor a reference type, especially an array of objects that are common in the actual application, the situation is different.
<body>
<div hg-repeat= ' item in Items ' >
<input ng-model= ' ITEM.A '/><span>{{item.a}}</span>
</div>
<div>change Count: {{count}}</div>
<script>
Angular.module (' myApp ', [])
. Run ([' $rootScope ', function ($rootScope) {
$rootScope. Count = 0;
$rootScope. Items = [
{"A": 1},
{"A": 2},
{"A": 3},
{"A": 4}
]
$rootScope. $watch (' Items ', function () {
$rootScope. count++;
},true)
}]);
</script>
</body>
After angular 1.1.4, a $watchcollection () method has been added to monitor the array (that is, the collection), where performance is between strict monitoring and referential monitoring, i.e. it does not monitor the properties of each item in the group. However, you can react to the increase or decrease of items in the array.
Simply change the $rootscope. $watch to $rootscope. $watchCollection:
$rootScope. $watchCollection (' Items ', function () {
$rootScope. count++;
})
This is the recommended way to work with collections.
Three $digest and $apply
1. After calling the $scope. $digest (), the $digest loop begins. Suppose you change one of the data in a scope in the handler function corresponding to a ng-click instruction, and ANGULARJS automatically triggers a round of $digest loops by calling $digest (). When the $digest loop starts, it triggers each watcher. These watchers check whether the current model value in scope differs from the model value that was last computed. If it is different, then the corresponding callback function will be executed. The result of invoking the function is that the contents of the expression in the view are updated.
Angularjs does not call $digest () directly, but instead calls $scope. $apply (), which calls $rootscope. $digest (). Therefore, the round $digest cycle starts at $rootscope and then accesses all watchers in the children scope.
Normally, in the context of angular, modifying the data source will automatically trigger. $apply just made $digest a package to provide manual triggering, then why do I need to trigger it manually? Because if it is not in the context of angular, such as browser DOM event, settimeout execution, in this case, angular cannot get to the event, so, by using apply to manually trigger, in the parameters of apply to modify the data source.
2. For example:
<body ng-app= "MYAPP" >
<div ng-controller= "Messagecontroller" >
Delayed message: {{Message}}
</div>
</body>
Angular.module (' myApp ', []). Controller (' Messagecontroller ', function ($scope) {
$scope. getMessage = function () {
SetTimeout (function () {
$scope. Message = ' fetched after 3 seconds ';
Console.log (' message: ' + $scope. message);
}, 2000);
}

$scope. GetMessage ();

});
By running this example, you will see that after two seconds, the console does show the updated model, however, the view is not updated. Maybe you already know that we forgot to call the $apply () method. Therefore, we need to modify getmessage ().
Angular.module (' myApp ', []). Controller (' Messagecontroller ', function ($scope) {
$scope. getMessage = function () {
SetTimeout (function () {
$scope. $apply (function () {
Wrapped this within $apply
$scope. Message = ' fetched after 3 seconds ';
Console.log (' message: ' + $scope. message);
});
}, 2000);
}

$scope. GetMessage ();

});

AngularJS $watch $digest $apply

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.