JSライブラリ > Handlebars.js

Handlebars.js

書きかけの記事

Handlebars.js とは

JavaScriptテンプレートエンジン
双方向データバインドの機能等はなく、単純なテンプレートエンジン。

利用準備

http://handlebarsjs.com/ からダウンロードした js をヘッダで読み込む

<head>
<meta charset="utf-8" />
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="handlebars-v3.0.3.js"></script>
</head>
 ・
 ・

単純な値の展開

HTML

<script id="entry-template" type="text/x-handlebars-template">
  <div class="entry">
    <h1>{{title}}</h1>
    <div class="body">
      {{body}
    </div>
  </div>
</script>

<div id="area1"></div>

<input id="btn1" type="button" value="test1" />
<input id="btn2" type="button" value="test2" />

JavaScript

$(function(){
    var source   = $("#entry-template").html();
    var template = Handlebars.compile(source);
    var context = {title: "My New Post", body: "This is my first post!"};
    var html    = template(context);
    $("#area1").html(html);

    $("#btn1").on("click", function(){
        var html = template({ title : "title1", body : "test1 body!!!" });
        $("#area1").html(html);
    });
    $("#btn2").on("click", function(){
        var html = template({ title : "title2", body : "test2 body!!!" });
        $("#area1").html(html);
    });

単純な値の展開(scriptタグにテンプレートを記述しない場合)

HTML

<div id="area1">
  <div class="entry">
    <h1>{{title}}</h1>
    <div class="body">
      {{body}
    </div>
  </div>
</div>

<input id="btn1" type="button" value="test1" />
<input id="btn2" type="button" value="test2" />

JavaScript

$(function(){
    var source   = $("#area1").html();
    var template = Handlebars.compile(source);
    var context = {title: "My New Post", body: "This is my first post!"};
    var html    = template(context);
    $("#area1").html(html);

    $("#btn1").on("click", function(){
        var html = template({ title : "title1", body : "test1 body!!!" });
        $("#area1").html(html);
    });
    $("#btn2").on("click", function(){
        var html = template({ title : "title2", body : "test2 body!!!" });
        $("#area1").html(html);
    });
});

リストの展開

ビルトインヘルパー(http://handlebarsjs.com/builtin_helpers.html)の each block helper 等を利用する事により実現可能。
また、registerHelper を利用して独自の展開方法を指定する事も可能。(後述:ラップ例を参照)

HTML

<div id="div1">
{{#each people}}{{firstName}} {{lastName}}<br />{{/each}}
</div>

JavaScript

$(function(){
    var data1 = {
      people: [
        {firstName: "Yehuda", lastName: "Katz"},
        {firstName: "Carl", lastName: "Lerche"},
        {firstName: "Alan", lastName: "Johnson"}
      ]
    };

    var source1   = $("#div1").html();
    var template1 = Handlebars.compile(source1);
    var html1    = template1(data1);
    $("#div1").html(html1);
});

条件分岐

条件分岐もビルトインヘルパー(http://handlebarsjs.com/builtin_helpers.html)として提供されている。

<!-- 変数 author が定義されているかどうかで表示内容を変える -->
<div class="entry">
  {{#if author}}
    <h1>{{firstName}} {{lastName}}</h1>
  {{else}}
    <h1>Unknown Author</h1>
  {{/if}}
</div>

※ 反対に変数が定義されていない時に展開する場合は、unless を使用。

ラップ例

先にデザインだけを行いたいケースで scriptタグにテンプレートを記述するのが嫌な場合。
以下のような感じでラップすれば、(自分的には)そんなに違和感がない。

HTML/CSS

<style type="text/css">
.my_tmpl {
  .display:none;    /* デザイン時はコメントアウトしておく */
}
</style>

<table border="1">
    <tr>
        <th>id</th>
        <th>isbn</th>
        <th>title</th>
        <th>price</th>
    </tr>
    <tr id="mylist" class="my_tmpl">
        <td>{{id}}</td>
        <td>{{isbn}}</td>
        <td>{{title}}</td>
        <td>{{price}}</td>
    </tr>
</table>

JavaScript

var templates = {};
$(function(){

    ///// 共通処理 START /////
    // {{#list ... }} ... {{/list}}の展開を行うヘルパ関数を登録
    Handlebars.registerHelper('list', function(items, options) {
      var out = "";
      var preTag = options.hash["type"] ? "<" + options.hash["type"] + " class=\"list_row\" >" : "";
      var sufTag = options.hash["type"] ? "</" + options.hash["type"] + ">" : "";
      for(var i=0, l=items.length; i<l; i++) {
        out = out + preTag + options.fn(items[i]) + sufTag;
      }
      return out;
    });

    // テンプレートHTMLを取得する関数
    var getListTempl = function(id, opts){
        opts = opts || {};
        var tmpl    = $("#"+id).html();
        var varName = opts["row"] || $("#"+id).data("row") || "row";
        var tagName = $("#"+id)[0].nodeName;
        var className = ""; // TODO
        var source  = "{{#list " + varName+ " type=\"" + tagName + "\" class=\"" + className+ "\" }}" + tmpl + "{{/list}}";
        return source;
    };

    // 指定されたIDの要素に変数の内容を展開する関数
    var renderList = function(id, data, opts){
        var template = null;
        var templId = id + "_" + JSON.stringify(opts);
        if (!templates[templId]){
            var source = getListTempl(id, opts);
            templates[templId] = Handlebars.compile(source);
        }
        var template = templates[templId];
        var html     = template(data);
        $("#" + id).parent().find(".list_row").remove();   // 再描画用に、既に動的に展開されている部分をいったん削除(ここらへんは状況に応じて要考慮)
        $("#" + id).after(html);
    };
    ///// 共通処理  END  /////

    // リストの描画
    var listData = {
         book : [
             {id: 1, isbn : "test1", title : "タイトル1", price : 1000 }
            ,{id: 2, isbn : "test2", title : "タイトル2", price : 2000 }
            ,{id: 3, isbn : "test3", title : "タイトル3", price : 3000 }
            ,{id: 4, isbn : "test4", title : "タイトル4", price : 4000 }
            ,{id: 5, isbn : "test5", title : "タイトル5", price : 5000 }
        ]
    };
    renderList("mylist", listData, { row : "book"});
});

トップ   差分 バックアップ リロード   一覧 単語検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2015-08-12 (水) 19:02:53 (3381d)