Rough sketch of how is the flow of data in Mercury.
│
Event channels <───────────── dom-delegator (events)
│ │ ^
V (imperative) │
View state │ DOM
│ ^
V (reactive) │ │
render (functional) ─────> VDOM diff & patch
│
mercury app │ mercury framework
http://raynos.github.io/mercury/examples/shared-state.html
var document = require('global/document');
var hg = require('../index.js');
var h = require('../index.js').h;
function App() {
var state = hg.struct({
text: hg.value(''),
handles: hg.value(null)
});
state.handles.set(hg.handles({
change: function setText(state, data) {
state.text.set(data.text);
}
}, state));
return state;
}
App.render = function render(state) {
return h('div', [
h('p.content', 'The value is now: ' + state.text),
h('p', [
'Change it here: ',
h('input.input', {
value: state.text,
name: 'text',
type: 'text',
'ev-event': hg.changeEvent(state.handles.change)
})
])
]);
};
hg.app(document.body, App(), App.render);
- The entire view is a single complex vtree
- The entire view state is a single complex immutable object.
- Rendering function is pure, it takes just the view state (disclaimer: hooks & widgets are not pure).
- You declare all user input as channels up front in your view state.
| Framework | Language | Arch. structure | Internal component state | Rendering | App state |
|------------|---------------|-----------------|--------------------------|----------------------|-------------|
| React/Flux | JavaScript | Cyclic | Allowed (=> impure) | Reactive | Interactive |
| Mercury | JavaScript | Acyclic | Disallowed (=> pure) | Reactive | Interactive |
| Cycle | JavaScript | Cyclic | Allowed (=> impure) | Reactive | Reactive |
| Om | ClojureScript | Cyclic? | Allowed (=> impure) | Interactive/Reactive | Interactive |
| Quiescent | ClojureScript | Cyclic | Disallowed (=> pure) | Reactive | Interactive |
In all of these, there is no two-way data binding. Sometimes some of these might employ one-way data binding.