I'm working on improving performance of ng application. I've meet with strange side effect of FastClick.
It leads to multiple dispatch Events (see attached image) and to a row of $digest which I would prefer to avoid.
Does anybody know how to cope with such behavior?
Actually it wasn't "fast click" issue.
It was partially my mistake.
I had a few ng-click handlers that is fired during the event bubbling, and angular-touch ways to $digest on every node element that have ng-click event listener.
Related
I want to remove watchers from my Angular JS application. To do that, I use the :: keyword to apply one-time binding instead of watchers.
When I want to verify it using Angular Batarang or just plain scope.$$watchers (I think it works in the same way), I see that they still count as watchers.
Why are they appearing on the watchers list? What did I miss?
I think the $watcher is still attached to the value due to the nature of angular binding. But the single binded values won't be reevaluated every $digest cycle. So there is performance improvement using single-bind. See great documentation : one time binding
This may not be a Mithril specific question but VM DOM diffing in general. While "redrawing" a page and you attach a new event handler, remove an event handler, or change the event handler associated with an event such as "onclick", it seems that the VM DOM diffing will not detect the change and I have to explicitly force a rerendering of the "real" DOM.
Is there a good pattern to handle these situations.
In Mithril specifically, onclick and all the on-handlers automatically trigger a redraw after the handler function has completed. However, if your onclick handler does real DOM manipulation (3rd party libraries such as jQuery or an animation suite) you need to use the config attribute:
http://lhorie.github.io/mithril/mithril.html#the-config-attribute
which gets called after the page has been rendered.
With regards to changing event handlers, it depends on when in the render cycle you make the change. I'd have to see some code. If it's not too inconvenient, calling redraw manually is not a bad thing. If the redraw strategy is "diff" you won't pay a penalty.
And lastly, if you are introducing your own events, consider using m.startComputation/m.endComputation in your event handlers. These provide much finer grain control and a redraw is automatically called.
http://lhorie.github.io/mithril/mithril.computation.html
What happens inside AngularJS when a event is fired with the Angular internal event system?
From a performance point of view, should I tend to use watches or events to update parts in my application?
When a JS event is fired, it is typically handled in the same way that all JS events are handled - there is nothing special or unique about this.
However, angular will wrap the handler inside of an $apply block so that after it executes the function, it can trigger a digest cycle:
$scope.$apply(function(){
$element.on('click',function(e){
...
});
})
A digest cycle iterates over all your scope variables, compares each one with the previous value to determine if anything has changed, and if it has, then their corresponding $watch handlers are called to update the view.
Since you are using angular, set up $watch expressions when you want to detect that a model on your scope has changed, and then do any DOM manipulations from inside your $watch handler. If you are concerned about performance, make sure your $watch function is optimized (i.e. avoid full jquery, avoid expensive query selectors, minimize DOM manipulation etc.)
To answer your question, you should use $watches to monitor changes to your models, and $watch functions to update your view.
I have a directive which encapsulates a dialog box, and it's almost completely isolated from the surrounding scopes: the only way to communicate with/from it is by firing events. For instance, dialog box commands such as "Apply", "Save", "Delete" or "Turn the lights off" are issued by clicking buttons and firing corresponding events which other scopes may be waiting for.
As we don't know which scopes are registered to handle any specific events, I've resorted to broadcast the dialog's command events all the way up from $rootScope, and of course it works. However, if an event handler changes the model, the view isn't updated, because there's no $apply or $digest following the event firing.
Here lies my dilemma: where to call $digest from? Or am I very misguided about the whole thing?
Since $broadcast is synchronous, I suggest that the code that is calling $broadcast should call $rootScope.$apply() after calling $broadcast, if that code is running "outside" AngularJS. (If that code is running "inside" Angular, $apply() should not be needed.)
First all, I want to be clear that my question is NOT about the $destroy event associated with AngularJS Scope.
AngularJS patches jQuery to make all jQuery's DOM destruction apis to fire a $destroy event on all DOM nodes being removed. jqLite (comes with AngularJS) also behaves in the same way, if no jQuery is used. I have seen the $destroy event been used (ie. bind to) in a few occurrences in AngularJS' source. But still, I cannot reason what are some practical uses of binding to the $destroy event on DOM elements being removed. Please enlighten me.
Here is a valid issue from the AngularJS github repository that could be solved with this event: https://github.com/angular/angular.js/issues/3237
Check this fiddle: http://jsfiddle.net/Amh8W/2/
$element.on('$destroy', function() {
$scope.window.close();
});
Window is closed when directive is removed - try to handle that in another way. $destroy has functionalty similar to destructor.