angularjs - Does Angular create a new watcher if one already exists? -
consider:
angular .module('app', []) .controller('maincontroller', function($scope) { $scope.$watch('bool', function(newval, oldval) { }); console.log($scope); });
and
<body ng-controller='maincontroller'> <p ng-class="{'blue': bool, 'red': !bool}">ngclass</p> <p ng-show='bool'>ngshow</p> <input type='checkbox' ng-model='bool' /> </body>
it seems there 3 watchers being created:
- from
$scope.$watch
. - from
ngshow
. - from
ngclass
.
(note: directives involved in data binding use $scope.$watch internally.)
i have thought since they're watching bool
property, there'd 1 watcher , it'd have multiple listener callbacks.
edit: case it's saying, "has bool
changed? if run cb1
. has bool
changed? if run cb2
. has bool
changed? if run cb3
." or case it's saying, "has bool
changed? if run cb1
, cb2
, , cb3
." if former, why on latter?
questions:
- is interpretation correct? there multiple watches being registered?
- what implications performance?
- bonus: if interpretation correct , multiple watchers being added, why designed this? why changes
bool
3 times instead of 1?
example 2) - want make sure 2 passwords in form match, , if don't, show error. assume have:
ng-class="{invalid: myform.myinput1.$touched && ctrl.myinput1 != ctrl.myinput2}"
say want use $setvalidity
update validity of form. might idea do:
ng-class="{invalid: myform.myinput1.$touched && ctrl.functiontocheckinputs(myform)}"
and call $setvalidity
inside of functiontocheckinputs
rather using $scope.$watch
, doing $setvalidity
inside of it? because latter adds additional watcher (presumably).
there multiple $watchers being registered. in fact, if had 2 exact expressions:
$scope.$watch("foo", cb1) $scope.$watch("foo", cb2)
you'd still 2 $watchers.
to answer question - former case, i.e. "if "foo"
expression changed, run cb1
, if "foo"
expression changed, run cb2
, etc... why? because, $watcher potentially change return value of $scope.foo
; not in callback, in expression itself. angular needs re-evaluate expressions every time account possibility.
the length of digest cycle plays significant factor on performance.
first, number of $watchers, cause watched expression or function evaluate. so, reducing number of $watchers, preferring one-way two-way watch, or use one-time watch suitable, improves performance.
second, complexity of watched functions. these functions should fast - ideally, not more getters. example, avoid following:
<div ng-class="{active: isactive(id)}">
$scope.isactive = function(id){ (var i=0; i<items.length; i++){ if (items[i].id == id && items[0].active) return true; } return false; };
Comments
Post a Comment