Mithril VM DOM diffing does not detect diff in attached event handler - reactjs

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

Related

What are React ...Capture events?

There is a duplicate for each event on react audio and video tags, for example it has onCanPlayThrough property and onCanPlayThroughCapture as well. Behaviour for both of them in the browser is completely the same.
Do we need to use ...Capture events instead of standard events? What is the main idea for them? Where can I find information about them.
This is covered in the React documentation here, though it's easy to miss:
The event handlers below are triggered by an event in the bubbling phase. To register an event handler for the capture phase, append Capture to the event name; for example, instead of using onClick, you would use onClickCapture to handle the click event in the capture phase.
DOM events have multiple phases (see diagram below), which are (in order):
Capture
Target
Bubbling
Normally we use target or bubbling (addEventListener's false third param [the default]), but there are rare occasions where you want to hook into the capture phase instead (third param = true). The ...Capture handlers let you do that.
They are not the same and the documentation also states this:
The event handlers below are triggered by an event in the bubbling phase. To register an event handler for the capture phase, append Capture to the event name; for example, instead of using onClick, you would use onClickCapture to handle the click event in the capture phase.
The effect is the same as in regular DOM bubbling/capturing. If you want to capture, the event will fire on a parent first. On bubbling it will fire on the actual element first and then bubble to parents.

attaching event handlers to react components using jquery

I know this is the proper way to do -
Attach handlers on react components using attributes such as onClick, onBlur etc.
If attaching custom events then attach them in componentDidMount so that it always gets attached on every rendering.
https://facebook.github.io/react/docs/interactivity-and-dynamic-uis.html#under-the-hood-autobinding-and-event-delegation
However, what happens when an event is attached to a DOM element using jquery ? Why am I not able to listen to those events ? I am attaching them out side componentDidMount. However the event handler should get trigerred the first time atleast ?
I was debugging some react code which was attaching an handler to it directly, but it was not trigerring the handler at all. Why was that ?
Without code example it's difficult to know for sure but more than likely you're trying to bind an event using jQuery to some react-generate DOM element. So depending where you do the bind, you're probably using a jQuery selector which returns no results because React hasn't rendered that element to the DOM at the time the selector is being run.
This is why, if you are going to use jQuery binding, you should make sure you do so as part of the component lifecycle that ensures the element is actually rendered to the DOM before you are trying to select it with jQuery. So that's why the recommendation is to put this kind of code inside componentDidMount and clean it up in componentWillUnmount.

AngularJS Events vs Watches

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.

How can I "integration test" my AngularJS $destroy event handler?

I've written code in my controllers to clean up resources on a $destroy event. It's straightforward to write unit tests to verify the operation of my cleanup method, but it's reasonable to wonder this: When will my app ever get a $destroy event? What can I do as a user in my browser to make my app get a $destroy event?
From the docs
Removes the current scope (and all of its children) from the parent
scope. Removal implies that calls to $digest() will no longer
propagate to the current scope and its children. Removal also implies
that the current scope is eligible for garbage collection.
The $destroy() is usually used by directives such as ngRepeat for
managing the unrolling of the loop.
Just before a scope is destroyed, a $destroy event is broadcasted on
this scope. Application code can register a $destroy event handler
that will give it a chance to perform any necessary cleanup.
Note that, in AngularJS, there is also a $destroy jQuery event, which
can be used to clean up DOM bindings before an element is removed from
the DOM.
http://docs.angularjs.org/api/ng/type/$rootScope.Scope
It appears there are a couple of things related to $destroy. My basic understanding of this is that any time a scope is no longer needed navigating away from some view and now the controller/scope used for that view is no longer needed or some DOM element is removed $destroy is called. The places I've seen this actually in use are for cleaning up timers or listeners so that the memory can be garbage collected.

What is the point/utility of addEvents? When would it be useful?

I saw that it adds events to an Observable. However, you would only add it if you would fire it at some point. So, if you add the firing of the event at some line in your code, it was useless to put it into addEvents in the first place and when you don't place the fireEvent in your code then it was pointless to include it in addEvents. What am I missing?
If you are adding custom events with your component then you must add the events with addEvent before you can fire the events with fireEvent. Adding and firing events is useful in binding custom components together without explicitly referencing them.

Resources