mithril.js v0.2.5のサンプルであるtodoを v1.0.0に書き直してみた
はじめに
mithril.jsの公式サイトにサンプルとしてtodoアプリがある。
1.0.0になってそのサンプルがなくなっていたので、独自で作り変えてみる。
なるべく公式のサンプルのソースを残したまま実装してみる。
http://mithril-ja.js.org/getting-started.html
環境
electron 1.4.15
mithril 1.0.0
ソースコード
早速ソースコードを晒してみる。
https://github.com/xheimdal/mithriljs-sample-code/tree/master/todo-v1.0.0
mithril 0.2.5のソースと見比べながら見てほしい。
const todo = { //TodoListクラスはtodoの配列 list: new Array, //Todoの内容を保持する変数 description: stream(""), //リストのモデルを作成 listModel: function(data){ this.description = stream(data.description); this.done = stream(false); }, //初回処理 oninit: function(vnode) { //Todo追加処理 vnode.state.add = () => { return function() { if (vnode.state.description()) { vnode.state.list.push(new vnode.state.listModel({description: vnode.state.description()})); vnode.state.description(""); } } }; }, //ビュー view: function(vnode) { return m("html", [ m("body", [ m("input", {onchange: m.withAttr("value", vnode.state.description), value: vnode.state.description}), m("button", {onclick : vnode.state.add()}, "追加"), m("table", [ vnode.state.list.map(function(task, index) { return m("tr", [ m("td", [ m("input[type=checkbox]", {onclick: m.withAttr("checked", task.done), checked: task.done()}) ]), m("td", {style: {textDecoration: task.done() ?"line-through" : "none"}}, task.description()), ]) }) ]) ]) ]); } } m.mount(document.getElementById("root"), todo);
内容
公式のサンプルではMVCモデルを意識して作られており、役割分担がわかりやすかった。
今回、書き換えた際は、MVCを考えずに書き換えた。
理由としては、1.0.0からコンポーネント内にvnodeが使えるようになったため、できる限りvnode内で処理してみたかったから。
oninitやviewはそれぞれ機能を持っていて、それらの関数の引数をvnodeと書いている。
listやlistModelなどコンポーネント内で宣言したものは、vnode.state.list
などのように書くことで参照することができる。
これが中々便利で、関数も第一引数のみ書けば、vnode上の情報を色々参照できる。
今回は各引数をvnodeと意味ありげに書いているが、わかりやすくするための例であり実際はv.state.listやval.state.fugaなど任意の名前で書いてよいです。
※始めはvnodeという引数の名前に特別な意味があると勘違いしていたなんて、恥ずかしくて言えない。。。orz
また、vnode.stateと書くのが長いので、こんな感じに短縮して書いた方がいいかもしれない。
//初回処理 oninit: function(v) { let vs = v.state //Todo追加処理 vs.add = () => { return function() { if (vs.description()) { vs.list.push(new vs.listModel({description: vs.description()})); vs.description(""); } } }; }, //ビュー view: function(v) { let vs = v.state return m("html", [ m("body", [ m("input", {onchange: m.withAttr("value", vs.description), value: vs.description}), m("button", {onclick : vs.add()}, "add"), m("table", [ vs.list.map(function(task, index) { return m("tr", [ m("td", [ m("input[type=checkbox]", {onclick: m.withAttr("checked", task.done), checked: task.done()}) ]), m("td", {style: {textDecoration: task.done() ?"line-through" : "none"}}, task.description()), ]) }) ]) ]) ]); }
まとめ
今までMVCを意識しながら書いていたが、mithril.jsのvnodeの特徴を活かしたコーディングをしてみた。
出来上がったものは、思ったよりすっきりと、まとまったソースが出来たと思う。
ただ何でもかんでもコンポーネント内に宣言してもいいのかという懸念点があり、さじ加減はわからない。
出来上がったソースの可読性が高ければ、何でもいいかもしれない。
また今回使っていないが、ライフサイクルメソッドであるoncreateやonupdateを使えばより柔軟に状態ごとの処理が書けるようになる。
まだうまく扱えきれていないが、出来る人が書けば、うまく活用できると思う。
今日はここまで。引き続き色々サンプルを届けていくので、乞うご期待!