Reputation: 1156
I have a pretty basic question about Angular watches. Say I have following in the link function of my directive:
scope.$watch(function(){
return element.isVisible();
}, myFuncUponVisibleChange);
Is this going to be the same as:
scope.$parent.$watch(function(){
return element.isVisible();
}, myFuncUponVisibleChange);
In other words, is Angular watching for the visibility of the same element in both cases above?
Upvotes: 1
Views: 49
Reputation: 222369
Yes, both scope watchers watch on the same element, because element
refers to particular object, and it was referenced in watcher function.
And yes, there is a substantial difference.
A lot of performance issues in AngularJS are caused by the fact that digest cycles affect the entire scope hierarchy. In other words, $scope.$apply()
triggers all watchers from top to bottom.
Once the application is complex enough (it always depends on client and app, but the crucial point is often estimated at ~1000 watchers for simplicity), it starts to become unresponsive on digests.
A good way to optimize this is to encapsulate directive changes and keep directives from announcing digests on root scope, unless global digest is the desired behaviour. In this case $scope.$digest()
may be called instead of $scope.$apply()
(the fundamental difference between those two is that the latter calls $rootScope.$digest()
).
Here comes the difference. scope.$parent.$watch(...)
watcher won't be triggered on $scope.$digest()
but it will be on $scope.$apply()
. And it shows why directive isolation is important and why referring parent scope from child is bad habit.
Another unpleasant surprise is that scope.$parent.$watch(...)
may cause memory leaks. If the element that owns scope
was destroyed, the watcher won't be cleaned up automatically. And it will refer to detached element
, preventing the object from being garbage-collected.
$scope.$parent
is evil.
Upvotes: 1
Reputation: 6404
Yes it is. What $element
is does not change because you are capturing the $element
reference that you have in that scope (JavaScript scope, not Angular scope) when you are declaring that function.
Now if you did something like this:
scope.$parent.$watch('$element.isVisible()', myFuncUponVisibleChange);
Then that would be totally different, because at that point you would be referencing the $element
from the parent scope, not the other scope.
Upvotes: 1