サンプルコードの説明
今回のサンプルコードの処理を図を使って説明すると、次のようになります。
- 「m.mount」実行後、Controllerの処理が実行されます。
- Controllerで各Modelからデータを取得し、thisに格納します。
- Viewの第1引数にcontrollerが入っているので、必要なデータを抽出しレンダリング内容を定義します。
- Controller処理完了後、初回のレンダリング処理が行われます。
- レンダリングされたHTMLでイベントをキャッチすると、Controllerで定義しているメソッドを実行します。
- ControllerのメソッドからModelのメソッドを実行し、データの変更を行います。
- イベント実行のタイミングで、再度レンダリング処理が行われます。
Mithrilの主要メソッドの説明
m.mount
Mithrilで定義したアプリケーションを実行します。controllerの実行とViewの初回レンダリングを行うメソッドです。
m.mount(document.getElementById("root"), { controller: myCtrl, view: myView });
引数 | 名前 | 説明 |
---|---|---|
第1引数 | root | レンダリング対象のDomを指定 |
第2引数 | module | controllerとviewを定義 |
「m.mount」を実行すると、まずデータの監視処理が開始され、controller Classがインスタンス化されます。Controllerの処理完了後、データの監視処理が停止。viewのレンダリング通知が実行されます。
viewで生成されたDOMは「root」で設定した要素内に展開されます。
v0.1.34までは「m.module」という名称でしたが、v0.2.0から「m.mount」に変更されました。ただし、互換性は確保されているので、v0.2.0でも引き続き「m.module」で実行することは可能です。
m
VirtualDOMの生成に使用する関数です。基本はView側で定義します。
Reactの「React.createElement」と同等の動作をします。CSSセレクタの形式でも定義できるのが特徴と言えます。
m("br") //<br> m("div", "Hello") //<div>Hello</div> m("div", {class: "container"}, "Hello"); //<div class="container">Hello</div> m("div.container", "Hello"); //<div class="container">Hello</div> m("div[href='hoge.html']", "Hello"); //<div href="hoge.html">Hello</div>
- 第1引数にCSSセレクタを定義することで、要素が作成されます。
- 第2引数に設定する属性と値をobject形式で指定できます。省略も可能です。
- 第3引数に要素の値を入力します。
JSXのようにDOM形式でViewを書ける、MSXというコンパイラも用意されています。MSXを使いDOM形式でViewを定義するのが現在主流になっていますが、今回は内部の挙動を分かりやすく見るために、上記の形式で記載させていただいています。MSXについての詳細は次回お話します。
m.withAttr
「onclick」や「onchange」などのイベント発生時に実行する関数を定義する際に使用します。DOMのイベントハンドラに設定する形式で使用します。
var myCtrl = function(ctrl) { var that = this; this.text = m.prop("first"); this.onChangeText = function(v){ that.text = m.prop(v); }; } var myView = function(ctrl){ return [ m("p", ctrl.text() ), m("button", { onclick: m.withAttr("value", ctrl.onChangeText), value:"change" }, "change value"), ]; };
引数 | 名前 | 説明 |
---|---|---|
第1引数 | prop | withAttrCallbackの第1引数として渡す、属性名を指定。 |
第2引数 | withAttrCallback | callback関数を指定。第1引数にpropで指定した属性の値が入る。 |
m.prop
viewModel処理を簡易的に設定できるように用意された、getter/setterメソッドです。基本はcontrolleやmodelで使用します。
var myCtrl = function() { //set value this.name = m.prop("hoge"); //this.nameが関数に変更されます console.log(this.name); // -> function(){...} //get value console.log(this.name()); // -> "hoge" //change value this.name("fuga"); //get value console.log(this.name()); // -> "fuga" };
「m.withAttr」と連携することで、簡潔に処理を書くことができます。
var myCtrl = function(ctrl) { this.inputData = m.prop("") } var myView = function(ctrl) { return [ m("input", {onchange: m.withAttr("value", ctrl.inputData) }), m("p", ctrl.inputData()) ]; }
m.request
mithrilで通信処理を行うためのメソッドです。内部的にレンダリング監視処理が実行されるため、xhr通信を行う際は必須です。また、内部でm.propが使われています。
var myCtrl = function(){ //簡易的な利用方法 var data = m.request({method: "GET", url: "data.json"}); //success,error検知 var data2 = []; m.request({ method: "GET", url: "data.json" }).then( //success function(resp) { data2 = resp; alert("success"); }, //error function(resp) { alert("error"); } ); //パース処理後格納する場合 var data3 = m.request({method: "GET", url: "data.json"}) .then(function(resp){ return resp.filter(function(v){ return v.id === 2; }); }); //確認 this.onClick = function(){ console.log(data()); //-> [{id: 1, name: "John"}, {id: 2, name: "Mary"}] console.log(data2); //-> [{id: 1, name: "John"}, {id: 2, name: "Mary"}] console.log(data3()); //-> [{id: 2, name: "Mary"}] }; };