Do You PHP はてブロ

Do You PHPはてなからはてブロに移動しました

JsViewsチュートリアル - データが更新された時に独自のイベントハンドラを実行する

JavaScript製でjQuery非依存なテンプレートエンジンであるJsRender/JsViewsを使ったチュートリアルを書いてみようと思います。
以前に書いたエントリJsRender入門 - Do You PHP はてなも参照してください。

今回やること

JsViewsでデータリンクしたデータの更新を監視し、独自のイベントハンドラを実行する。

コード

<html>
<body>
<div id="list"></div>
<hr/>
<button id="code">update code</button>
<button id="name">update name</button>
<button id="color">update color</button>

<script src="https://code.jquery.com/jquery-1.11.1.min.js" type="text/javascript"></script>
<script src="js/jsviews.min.js" type="text/javascript"></script>
<script type="text/javascript">
// リンクされたデータの更新を監視し、イベントハンドラを実行する
$(function() {
    // データのオブジェクト
    var application = {
            log: [],
            fruits: {
                code: "01",
                name: "りんご",
                color: '赤'
            }
        };

    // テンプレートに名前をつけて登録する
    $.templates({
        pathTemplate: "#template"
    });

    // テンプレートlinkTemplate(#template)と変数applicationをリンクさせ、
    // レンダリング結果をid="list"に表示
    $.link.pathTemplate("#list", application);

    $(document)
        .on('click', '#code', function(ev) {
            $.observable(application.fruits).setProperty('code', application.fruits.code + '9');
        })
        .on('click', '#name', function(ev) {
            $.observable(application.fruits).setProperty('name', application.fruits.name + '!');
        })
        .on('click', '#color', function(ev) {
            $.observable(application.fruits).setProperty('color', application.fruits.color + '色');
        })

    // application.fruitsのnameプロパティもしくはcolorプロパティが
    // 更新された場合にハンドラが実行される
    $.observe(application, 'fruits.name', 'fruits.color', function(ev, args) {
        $.observable(application.log).insert([args.path + 'が' + args.value + 'に更新されました']);
    });
});
</script>

<script id="template" type="text/x-jsrender">
    <div>
        <p><span data-link="fruits.code"></span>:<span data-link="fruits.name"></span>(<span data-link="fruits.color"></span>)</p>
    </div>
    <div>
        {^{for log tmpl="#template_log"/}}
    </div>
</script>
<script id="template_log" type="text/x-jsrender">
    <li><span data-link="#data"></span></li>
</script>
</body>
</html>

説明

データリンクしたデータが更新されたタイミングで、ログ出力や視覚的なエフェクトをかけるなど何らかのハンドラを実行したい場合があるかと思います。JsViewsではこのための仕組みも用意されています。

$.observe([対象の変数], [プロパティへのパス1], [プロパティへのパス2], ... , [イベントハンドラ])

プロパティへのパスは1つ以上指定可能で、「対象の変数」が基準となります。先ほどのコード例では、application.fruitsオブジェクト直下にあるnameプロパティもしくはcolorプロパティが更新された場合にログ出力するイベントハンドラが実行されます。
プロパティへのパスですが、ワイルドカードが使えます。例えば、application.fruitsオブジェクト直下にあるすべてのプロパティが対象であれば、

$.observe(application, 'fruits.*', function(ev, args) {});

といった具合になります。
また、イベントハンドラ引数を2つ取ります。1つ目はjQueryのイベントオブジェクト、2つ目はJsViewsのイベントオブジェクトで更新前後の値やどういう更新を行ったのか?という情報が含まれます。
また、対象の変数に存在するすべてのプロパティに対してイベントハンドラを割り当てたい場合は、次の書式が利用できます。

$.observable([対象の変数]).observeAll([イベントハンドラ])

JSFiddleで動作を見る