heimdalの技術ノート

IT全般、Linux、Windows、プログラミング開発など、何でもござれ

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を編集するだけで良いように作成した。

heimdal.hatenablog.com

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の組み合わせも稀だし、
学ぶこともたくさんあるのでターゲットはかなり狭いかもしれない。

では今日はこの辺で。。。