inga(因果)は、軽量で拡張可能なリアクティブ・アダプターです。RxJSとvirtual-domを使っています。
よくあるTodo-MVCは100行ぐらいです。
特徴
- 軽量なこと。全ソース合わせても100行ちょっとしかないです。
- プラグインで拡張可能です。
- 副作用の処理をthunkで扱うストリームがデフォルトで付いているので、大抵のイベント処理はこれで済みます。
簡単なサンプル
例えばクリックする度にカウンタが増える、みたいなのは次のようになります。
var Inga = require("inga"); Inga.define({ domRoot:"#app", dataSource:new Inga.ActionStateStream({ initialState:{clickCount:0} }), virtualView:function(ctx){ return h("button", { "ev-click":function(ev){ ctx.action.emitUpdater(function(state){ state.clickCount++; }); } }, ctx.state.clickCount); } });
プラグインを使ったサンプル
例えばinga/plugins/scroll-pos
を組み込むと、こんな感じでレンダリング・コンテキストの状態オブジェクトにscrollPos
が合成されます。
var Inga = require("inga"); Inga.define({ domRoot:"#app", dataSource:new Inga.ActionStateStream({ initialState:{scrollPos:{x:0, y:0}}, // plugin 'scroll-pos' combines 'scrollPos' to status object. plugins:[ {module:require("inga/plugins/scroll-pos"), options:{combine:true}} ] }), virtualView:function(ctx){ return h("div", [ h("p", "x = " + ctx.state.scrollPos.x), h("p", "y = " + ctx.state.scrollPos.y) ]); } });
自前のストリームを合成するサンプル
デフォルトのストリームに、自分で作ったストリームを組み込む場合は次のようにcombine
アクションを定義します。
var Rx = require("rx"); var Inga = require("inga"); Inga.define({ domRoot:"#app", dataSource:new Inga.ActionStateStream({ initialState:{width:window.innerWidth}, actions:{ // extend default stream by your own source. combine:function(initial_state, upstream$){ var width$ = new Rx.Observable.fromEvent(window, "resize") .debounce(250) .map(function(event){ return window.innerWidth }) .startWith(window.innerWidth); return upstream$.combineLatest(width$, function(state, width){ state.width = width; return state; }); } } }), virtualView:function(ctx){ return h("p", "current window width = " + ctx.state.width); } });
その他
ライセンスはMITです。