müv.js is a small library for building reactive web apps.
müv.js is intentionally simple. You could write it yourself. The hard work was done by the authors of Snabbdom virtual dom and functional reactive programming libraries like RxJs. The trick is understanding how to compose these two things in order to build complex applications. The pattern for data flow and state change takes inspiration from the model/update/view architecture found in Elm.
Any library with a subscribe
method. Here are a few: RxJs, Bacon.js, Kefir, xstream, Most
HTML is represented using arrays. For example:
['a', {props: {href: 'http://todomvc.com'}}, 'TodoMVC']
['ul#frp-list', {},
['li.selected', {}, 'RxJs'],
['li', {}, 'Bacon.js'],
['li', {}, 'Kefir']]
The class
, props
, style
, and eventlistener
modules from Snabbdom are automatically loaded. See: https://github.com/snabbdom/snabbdom#modules-documentation for more information.
State is held inside the scan
method of the data stream and updates with every action that is pushed to the stream. Both the update
function and view
function should be pure. The render
function takes a stream and an element to render the stream of "HTML" to.
import { render } from '../../src/index.js';
import Rx from 'rxjs/Rx';
// Stream
let actions$ = new Rx.Subject();
// Model
let initModel = 0;
// Update
function update(model, action) {
switch (action) {
case 'add':
return model + 1;
case 'subtract':
return model - 1;
}
}
// View
function button(action, text) {
return ['button', { on: { click: e => actions$.next(action) } }, text];
}
function view(model) {
return (
['div', {},
button('subtract', '-'),
['span', {}, ` ${model} `],
button('add', '+')]
)
}
// Reduce
let model$ = actions$
.do(x => console.log('Actions', x))
.scan(update, initModel)
.startWith(initModel)
.do(x => console.log('Model', x));
// Render
let view$ = model$.map(view);
render(view$, document.getElementById('container'));
Q: What projects have you drawn inspiration from? A: Elm, Cycle.js, and Redux