electronを使ってmithril.js 超入門 m.prop m.withAttr編
はじめに
mithril.jsのAPIの中にm.propがあるが、それを使うパターンを紹介する。
m.propとは
mithril.js版のgetter/setter関数のAPIである。
変数に代入することで、getter/setter関数用のプロパティを作成する。
let hoge = m.prop("");
書き込む時は、
hoge("fuga");
呼び出す時は、
hoge();
のように書けば良い。
m.withAttrとは
ビューからモデル方向へのデータバインディングを実現するための関数。
m.propと組み合わせて使う。
準備
前の記事のapp.jsを編集するだけで良いように作成した。
m.propからget、setするパターンを何パターンか書くので、
そこから何か気づいてくれば良い。
※ちなみに、jsファイルを修正するだけであれば、electronを起動した状態で画面をリロードするだけで、適応される。 毎回、「electron .」でコマンド実行する必要はない。
パターン1
まずは、m.propもm.withAttrを使用しないパターン。
ボタンとテキストボックスを配置したシンプルな構成。
起動時に文字が入力され、ボタン押下時に文字が入力される。
ビューにあるonclickで関数を実行し、valueがその値を取得する。
//モデル let myModel = function(data) { this.hoge = ""; }; //ビューモデル let myVM = { init:function() { myModel.hoge = "初回読み込み"; }, btnClick: function() { myModel.hoge = "ボタン読み込み"; } }; //コントローラ let myCont = function() { myVM.init(); }; //ビュー let myView = function(ctrl) { return [ m("button", {onclick: myVM.btnClick}, "ボタン"), m("input[id=hello]",{value: myModel.hoge}) ] } //コンポーネント let myComponent = { controller: myCont, view: myView }; //描写 m.mount(document.getElementById("root"), myComponent);
パターン2
公式のサンプルソースを参考に、よりgetter/setterがわかるように改良した。
http://mithril-ja.js.org/mithril.withAttr.html
そこまで難しくないはず。
//双方向データバインディングのサンプル let myComponent = { model: function(name) { this.name = m.prop(name); }, controller: function() { this.user = new myComponent.model(""); }, view: function(ctrl) { return [ m("p",[ m("div","setter"), m("input", {onkeyup: m.withAttr("value", ctrl.user.name)}) ]), m("p", [ m("div", "getter" ), m("input",{value:ctrl.user.name()}) ]) ] } }; // 描写 m.mount(document.getElementById("root"), myComponent);
パターン3
パターン2のソースを分解したバージョン。 動作は変わらない。
//双方向データバインディング //モデル let myModel = function(name) { this.text = m.prop(name); }; //コントロール let myCtrl = function() { this.model = new myModel(""); }; //ビュー let myView = function(ctrl) { return [ m("p", [ m("div", "setter"), m("input", { //キーアップ時にテキストボックスの入力値(value)を //コントロールで生成したインスタンスにセットする onkeyup: m.withAttr("value", ctrl.model.text) }) ]), m("p", [ m("div", "getter"), m("input", { //コントロールで生成したインスタンスから //値をゲットする value: ctrl.model.text() }) ]) ] }; let myComponent = { controller: myCtrl, view: myView }; //描写 m.mount(document.getElementById("root"), myComponent);
パターン4
パターン3にビューモデルを追加したバージョン。
改良点が多いが、ビューから直接モデルを操作せず、
ビューモデルを挟む処理をすることで、役割がより分かりやすくなる。
(ソースコードは分かりやすいとは言っていない。。。orz)
//双方向データバインディング let myApp = {}; //モデル let myModel = function(name) { this.text = m.prop(name); }; myApp.vm = (function(){ let vm = {}; vm.init = function(){ vm.model = new myModel(); } return vm }()); //コントロール myApp.controller = function() { myApp.vm.init(); }; //ビュー myApp.view = function(ctrl) { return [ m("p", [ m("div", "setter"), m("input", { //キーアップ時にテキストボックスの入力値(value)を //コントロールで生成したインスタンスにセットする onkeyup: m.withAttr("value", myApp.vm.model.text) }) ]), m("p", [ m("div", "getter"), m("input", { //コントロールで生成したインスタンスから //値をゲットする value: myApp.vm.model.text() }) ]) ] }; //描写 m.mount(document.getElementById("root"), myApp);
最後に
いかがだったでしょうか。
ある程度パターンが掴めたのであれば幸いです。
書いていくとわかってくるが、大部分は純粋なjavascriptで構成されており、
mithrilを構築していく上で、javascriptの基本を押さえておく必要がある。
それが前提で、mithrilとnode.jsなどのモジュールを組み合わせていく。
私自身まだまだ未熟者だが、mithrilを学ぶことで、純粋なjavascriptの学習にも
繋がるので、上級者のみならず、初心者も是非とも挑戦して欲しいと思っている。
まあ、electron+node.js+mithril+html+cssの組み合わせも稀だし、
学ぶこともたくさんあるのでターゲットはかなり狭いかもしれない。
では今日はこの辺で。。。