Do You PHP はてブロ

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

JsRender入門

JsRender/JsViewsのチュートリアルを書いています。こちらもどうぞ→「jsviews チュートリアル」の検索結果一覧 - Do You PHP はてな

API叩いてJSONデータを取得し、その結果をJavaScriptで出力する。よくある場面だと思うんですが、これってどう実装してますか?
一番わかり易い方法は、コンテンツを文字列で生成してappendTo()なりhtml()する方法。

// JSONデータの取得

var contents = '<p>...'
             + ...;
$('#target').appendTo(contents);

直感的なんだけど、何だか今更感が漂います。かと言って、DOM操作するのも面倒だし、コンテンツのサイズが大きい場合やデザイン変更などメンテナンスが大変そう。。。
こういう時にテンプレートエンジンを使うとヨサゲ、ということで探してみるとJsRenderというjQuery非依存なテンプレートエンジンを見つけました。

ただし、


Warning: JsRender is not yet officially beta, though the APIs and code are now stable. JsViews, on the other hand, is still evolving (with a number of powerful features arriving), and its Beta is currently planned for late September or early October. Since this could lead to small API changes in JsRender (to accomodate JsViews integration) JsRender will not be declared officially Beta until around the same time. Thank you for you patience!

ということで、"もうじきβ版"という状態であることには注意です。

以下の内容はデモページの内容を基にしています。

使い方

ざっと以下の様な流れになります。

  1. テンプレートを定義する
  2. JSONデータを取得する
  3. データをテンプレートに渡してレンダリング
  4. レンダリングした結果をjQuery.appendTo()などで出力

以下はオブジェクトの配列を一覧表示する例です。

<html>
<body>
<!-- ここに一覧を表示する -->
<div id="list"></div>

<script src="http://code.jquery.com/jquery.js" type="text/javascript"></script>
<script src="js/jsrender.js" type="text/javascript"></script>
<script type="text/javascript">
$(function() {
    // データの配列(もしくはオブジェクト)
    var fruits = [
        { code: "01", name: "りんご" },
        { code: "02", name: "バナナ" },
        { code: "03", name: "パイナップル" }
    ];

    // id="list"に結果を表示
    $("#list").html(
        // テンプレート(id="template")にデータ配列fruitsを渡して
        // レンダリングし、結果文字列を受け取る
        $("#template").render(fruits)
    );
});
</script>

<!-- ここからテンプレートの定義 -->
<script id="template" type="text/x-jsrender">
    <div>
        {{:#index+1}}: <a href="/fruit/{{>code}}/detail">{{>name}}</a>
    </div>
</script>
<!-- ここまで -->
</body>
</html>

テンプレートの定義

上記のサンプルのように、type属性に"text/x-jsrender"という値を持つscriptタグにテンプレート内容を記述するのが基本形になります。
この他、事前にコンパイル済み名前付きテンプレートにする方法もあります。この場合、キーとしてテンプレート名、値としてテンプレート内容を指定します。

$(function() {
    $.templates({
        // .html()が必要
        idTemplate: $('#template').html(),
        // 文字列をそのまま指定することも可能
        stringTemplate: '<div>{{:#index+1}}: <a href="/fruit/{{>code}}/detail">{{>name}}</a></div>',
    });

    $("#list").html(
        // コンパイル済み名前付きテンプレートをレンダリングする
        $.render.stringTemplate(fruits)
    );
});

上の例ではJavaScriptコード内にテンプレートを記述してますが、XHRを使って外部ファイルを読み込んでテンプレートとすることもできます。

コンバータ

サンプルのテンプレート内に何気なく

{{>name}}

と書きましたが、これで<"'>がエスケープされたnameの値が出力されます。これは

{{html:name}}

の省略形で、":"以前はコンバータと呼ばれます。上記のhtmlコンバータはJsRenderの組み込みコンバータで、独自に実装することもできます。
また、意図してエスケープしない場合は"コンバータなし"とすれば良いので、

{{:name}}

のようになります。

if文とfor文

テンプレート内で条件分岐ループも記述可能です。以下、if文の例。

<script id="template" type="text/x-jsrender">
    <div>
        {{:#index+1}}: 
        {{if name != 'りんご'}}
            {{>name}}
        {{else}}
            <a href="/fruit/{{>code}}/detail">{{>name}}</a>
        {{/if}}
    </div>
</script>

デバッグ

テンプレート内の文法エラーがあった場合などはメッセージが表示されます。が、変数名のtypo等の場合は何も表示されません。。。これ、結構ハマるので、良い方法があったら教えて欲しいです(汗)
ちなみに、デフォルトでデバッグモードは有効で、

$(function() {
    $.views.debugMode = false;
});

で無効にできます。

まとめ

ざっとですが、こんな感じでテンプレート化できます。ここまでの内容だけでもかなり良い感じに使えますが、その他細かい機能があるのでそちらも見てみてください。

また、このJsRenderの作者さん(Boris Moore氏)がもう一つ、JavaScriptデータとviewをリンクさせる(データバインディング)jsViewsというライブラリを作っています。個人的には"ここ最近のヒット"となっているので、次のエントリで書こうかと思います。