ヽ(´・肉・`)ノログ

How do we fighting without fighting?

Mithril本をやる

O’Reilly Japan - Mithril をやる.

なぜやろうと思ったか.

世界最速でMithril本をリリースした話 を読んで,

趣味時間をすべて削って何かを学んでも、「100点」にはなりません。せいぜい、1つや2つに分野をしぼって、仕事時間も使い、たまには趣味時間も使ってフォーカスしてようやく1つや2つ語れるようになる、といったところ

「がっつりフルタイムでウェブ技術を追いかける時間は取れないけど、今の仕事に取り入れるべく、なるべく新しく、ウリになりそうなもの(Mithrilは高速)を効率よく学んでおきたい」という人

が僕のスキルセットで欠如しているクライアントサイドのツールのところにうまくハマりそうだなと思った.

という状態なので,複雑さの増大を防止するような割り切りがあって,ドキュメントが整備されているツールが嬉しい.

1 章 GUIのパターンとMithrilの概要

「あなたが指している MVC ってどれですか?」という話は数年-十年くらい前に web で良く話されていたように思う.

リッチクライアント時代のWebアプリケーションアーキテクチャパターンについて考える」というスライドで知識を整理させてもらったので,たまに見直すことがある.(よく忘れる)

他の物が3リッター以上のエンジンで車重2トンを超えるボディを引っ張る、 ベントレーコンチネンタルのようなラグジュアリーカー路線だとすると、 MithrilはCBR600RRか、Ninjaに例えることができます。

この例えはちょっと笑ってしまった. Ninja はバイクの中では重厚なイメージが僕にはあるけど, CBR600RR のバイクの中でも軽くて速くて切れ味バツグンのイメージには沿いますね.

2 章 Mithrilチュートリアル

2.1 最小限のMithrilアプリケーション

client/index.html で

<script type="text/javascript" src="mithril.min.js"></script> <!-- (2) -->
<script src="app.js"></script>                                <!-- (3) -->

となっているところ,一つめには type を宣言しているのに,二つめには type を宣言していないのはなぜなんだろう?

たぶん Mithril 関係ないけど,どうやって使い分けてるの?

2.2 ToDoアプリケーションを作ってみる

Todo = function(data) {new Todo したときに呼ばれるコンストラクタなのだよな. 久しく JavaScript をちゃんと書くことがなかったので忘れている.

function view() のところで (1) から (5) まで連番が振られている.文中には 1 と 2 しか出てきていないな. 番号が振られているところは説明があるのかなと思ったので戸惑った.

2.3 ローカル保存機能を追加する

本とは関係ないのだけど typo していて最初全然動かなかった.ギギギ

Function.prototype.bind() - JavaScript | MDN

bind は,呼び出す関数の中にある this が指すオブジェクトを外部から渡してやるためのもの.

vm.check.bind(task) は 「 vm.check という関数を呼び出す,そのとき vm.check の中に書いてある thistask で渡したものとする」 ということだ.

使い慣れていないから出てくると気をつけて読まないと間違えそうになる.

2.4 サーバ保存機能を追加する

m.request()関数はm.prop()で作成するのと同じプロパティのインタフェースを持つオブジェクトを返します。 通信が完了すると取得してきたデータが代わりに入ります。 MithrilはAJAXの通信終了を待って自動で再描画を行うので、通信完了時に何かをする必要はありません。

なるほど.サーバーと通信するなら m.request を使えばいいのだな.

2.5 本章のまとめ

・Mithrilではコンポーネントを作成し、m.mount()で登録する。 ・コンポーネントにはcontroller()とview()という2つの関数がある。 ・Mithrilでは、フレームワーク固有のベースクラスなどは要求されない。モデルも素のJavaScriptのままのクラス。 ・モデルの主要な部品はm.prop()で作成するプロパティ。 ・ビューモデルが、ビューとモデルの仲介をする。入力テキストなど、ビューの一時的な状態はビューモデルが持つ。 ・テンプレートはm()関数を使って、JavaScriptで組み立てる。 ・ビューへのバインディングはプロパティを渡せば行える。ビューからのバインディングはm.withAttr()を使う。 ・サーバとの通信はm.request()で、これを使えば再描画システムとの調整も不要。

なるほど.

3 章 Mithrilのコントローラ、モデル、ビューモデル

3.1 コントローラ

オブジェクトの寿命を知ると大体の役割もみえてくる.

コントローラはコンストラクタ関数としてコンポーネントと同じ寿命を持つオブジェクトを作るのに使われるため、コントローラもページと同じ期間だけ生存します。

3.1.1 コントローラが扱うデータ

基本

その他

3.1.2 コントローラの実装

3.1.3 後片付け処理

コンポーネントのアンロードは,だいたいページ遷移と同じと考えておこう.

3.2 モデル

アプリケーションが扱う領域のデータと手続き(ビジネスロジック -ショッピングの合計額や送料を計算するなど)を表現する要素

3.2.1 Mithrilのモデルのインタフェース

3.2.2 コンストラクタ

3.2.3 セッター・ゲッター

3.2.4 非同期アクセス

ヌルオブジェクトパターンだ

3.2.5 モデルの永続化

3.2.6 モデルのライフサイクルと名前空間

3.3 ビューモデル

ビューモデルの役割

  1. ビューの一時的な状態を保持するプロパティの保持
  2. ビューで定義するテンプレートから呼び出されるイベントハンドラの実装
  3. モデルへの参照を保持しておいて、ビューから参照しやすいようなアクセスメソッドを提供

var vm = {
    init: function () {
        vm.list = m.prop([]);        // 3. モデルへの参照を保持しておいて、ビューから参照しやすいようなアクセスメソッドを提供
        vm.description = m.prop(""); // 1. ビューの一時的な状態を保持するプロパティの保持 (ビューでこの関数がバインドされる)
        vm.add = function () {       // 2. ビューで定義するテンプレートから呼び出されるイベントハンドラの実装
            if (vm.description()) {
                vm.list().push(new Todo({description: vm.description()}));
                vm.description("");
            }
        };
    }
};

3.3.1 ビューモデルはコンポーネントの中?外?

どちらでもかまわない.

ただし,コンポーネントの中に置くと,ページ移動のたびに破棄されたり生成されたりする.

寿命をページより長く保ちたい場合は外に置くこと.

3.4 MithirlのAPIとレイヤー分けの目安

表3-1 を転載.

MVCVM
m()/m.withAttr()/m.trust()/m.component()XOXX
m.prop()OXXO
m.route()XXOX
m.request()OXXX
m.deferred()/m.sync()OXOO
m.redraw()/m.startComputation()/m.endComputation()OXOX

大きな規模だとこんな感じで使い所を分けるとよいそうだ.

3.5 大きなアプリケーションのファイル分割構成

横(model/controller/viewといったレイヤー)単位ではなく,縦(機能/コンポーネント)単位で分けるのを推奨している.

これはその方が僕も好きだ.

3.6 本章のまとめ

Mithrilがどのようなアーキテクチャでアプリケーションを実装して欲しいと考えているか説明

コントローラ
寿命はページと同じ.ビューモデルやモデルの参照を保持する
モデル
寿命はページより長い.コンストラクタにはオブジェクトを受け取れるようにしておく.プロパティは m.prop でラップしておく.
ビューモデル
寿命は(基本的に)ページと同じ.一時的な状態の保持/テンプレートからのイベントハンドラ/便利なアクセスメソッドの3つの役割.