Edited at

JavaScriptのテンプレートエンジンHandlebars入門

More than 3 years have passed since last update.

Handlebarsを知らないという同僚がいたので、まとめてみます。

ただのテンプレートエンジンでデータバインディングとかはないんですが、もし使いどころがあればご参考までに。

基本的には、

http://handlebarsjs.com/

に詳しく書いてあるので、そちらを見てください。


Handlebarsとは

Handlebarsとはいわゆるテンプレートエンジンで、

JavaScriptの値を参照してHTMLを生成できるもの。


書き方

テンプレートは

<div>{{name}}</div>

<div>{{age}}</div>

という書き方をします。

{{XXX}}内のxxxはJavaScriptのプロパティです。

{{XXX}}と書くことにより、JavaScriptの値を参照して、

それをHTMLとして生成します。

<div>{{person.name}}</div>

<div>{{person.age}}</div>

という書き方もできます。そのときは値を

   person : {

name: "Satoshi",
age : 33,
}
}

みたいに渡してあげることが可能です。


Handlebarsを試す

まずはjqueryとhandlebarsをインストールします。

$ bower install jquery handlebars

ではちょっと試しに書いてみましょう。


test.html

<html>

<head>
<script type="text/javascript" src="./bower_components/jquery/dist/jquery.min.js"></script>
<script type="text/javascript" src="./bower_components/handlebars/handlebars.min.js"></script>
<script type="text/x-handlebars-template" id="template">
<h1>{{name}}</h1>
<div>{{age}}</div>
</script>
<script>
window.onload = function() {
var source = $("#template").html();
var template = Handlebars.compile(source);
var values = {
name : "Satoshi Watanabe",
age : 33
};
var html = template(values);
console.log(html);
$("#contents").html(html);
}
</script>
</head>
<body id="contents">
</body>
</html>


これを行うことにより

<h3>Satoshi Watanabe</h3>

<div>33</div>

が表示できます。


build-inのhelper

Handlebarsにはいくつかhelperが用意されているので、それを紹介します。


each

eachはイテレータとして、要素を順番に使用することができます。

<table border="1">

{{#each momoclo}}
<tr>
<td>{{name}}</td>
<td>{{color}}</td>
</tr>
{{/each}}
<table>

とした場合、momocloオブジェクトの要素をひとつひとつ参照します。

    var source = $("#template").html();

var template = Handlebars.compile(source);
var values = {
momoclo : [
{name : "Kanako Momota", color: "red"},
{name : "Ayaka Sasaki", color: "pink"},
{name : "Shiori Tamai", color: "yellow"},
{name : "Momoka Ariyasu", color: "green"},
{name : "Reni Takagi", color:"purple"},
]
};
var html = template(values);
$("#contents").html(html);


if / unless

{{#if author}}

<h1>{{firstName}} {{lastName}}</h1>
{{else}}
<h1>Unknown Author</h1>
{{/if}}

authorがtrueになれば、firstName, lastNameを出力します。

なければ、else以下を実行します。

unlessはifの逆でauthorがfalseになれば、実行します。

{{#unless author}}

<h1>Unknown Author</h1>
{{else}}
<h1>{{firstName}} {{lastName}}</h1>
{{/unless}}


with

withはjavascriptのwithと同じです。

テンプレートを

    {{#with momoclo}}

<div>{{Kanako}}</div>
<div>{{Ayaka}}</div>
<div>{{Shiori}}</div>
<div>{{Momoka}}</div>
<div>{{Reni}}</div>
{{/with}}

javascriptを

var values = {

momoclo : {
Kanako : "red",
Ayaka : "pink",
Shiori : "yellow",
Momoka : "green",
Reni : "purple",
}
};
var html = template(values);

とかくと、出力は以下のようになります。

<body id="contents">

<div>red</div>
<div>pink</div>
<div>yellow</div>
<div>green</div>
<div>purple</div>
</body>


lookup

lookupはあるデータをとりだしてそれを別なデータを取り出すのに使うのに使ったりします。

たとえば、

var values = {

momoclo : [
{firstname : "Kanako", lastname : "Momota"},
{firstname : "Ayaka", lastname : "Sasaki"},
{firstname : "Shiori", lastname : "Tamai"},
{firstname : "Momoka", lastname : "Ariyasu"},
{firstname : "Reni", lastname : "Takagi"},
],
color : {
"Kanako" : "red",
"Ayaka" : "pink",
"Shiori" : "yellow",
"Momoka" : "green",
"Reni" : "purple",
}
};

というデータがあったとして、

momocloのfirstnameからcolorの値が取りたい時、以下のようにします。

    <ul>

{{#each momoclo}}
<li>{{lookup ../color firstname}}</li>
{{/each}}
</ul>

そうすると、以下のような出力が得られます。

<ul>

<li>red</li>
<li>pink</li>
<li>yellow</li>
<li>green</li>
<li>purple</li>
</ul>


その他(時間があったときに追記)


  • log

  • blockHelperMissing

  • helperMissing


自分でhelperを定義する

helperはHandlebars.registerHelper()を使って自分で定義することができます。

例えば、linkを生成する

Handlebars.registerHelper('link', function(text, url) {

return new Handlebars.SafeString(
"<a href='" + url + "'>" + text + "</a>"
);
});

というものを用意してあげると、

データを

    var values = {

momoclo : [
{name : "Kanako Momota", url: "http://ameblo.jp/momota-sd/"},
{name : "Ayaka Sasaki", url: "http://ameblo.jp/sasaki-sd/"},
{name : "Shiori Tamai", url: "http://ameblo.jp/tamai-sd/"},
{name : "Momoka Ariyasu", url: "http://ameblo.jp/ariyasu-sd/"},
{name : "Reni Takagi", url:"http://ameblo.jp/takagi-sd/"},
]
};

としたときは、以下のように書くことができます。

<ul>

{{#each momoclo}}
<li>{{link name url}}</li>
{{/each}}
</ul>

そうすると結果は以下のようになります。

<ul>

<li><a href="http://ameblo.jp/momota-sd/">Kanako Momota</a></li>
<li><a href="http://ameblo.jp/sasaki-sd/">Ayaka Sasaki</a></li>
<li><a href="http://ameblo.jp/tamai-sd/">Shiori Tamai</a></li>
<li><a href="http://ameblo.jp/ariyasu-sd/">Momoka Ariyasu</a></li>
<li><a href="http://ameblo.jp/takagi-sd/">Reni Takagi</a></li>
</ul>


プリコンパイル

Handlebarsにはプリコンパイルしておくことが可能です。

ページの読み込むときにコンパイルする必要がないので、こちらをやっておくてページの表示が早くなります。

handlebarsのnpmでインストールしておき、使います。

$ npm install handlebars

テンプレートファイルを用意します。


test-template.hbs

<div>{{person.name}}</div>

<div>{{person.age}}</div>
<div>{{person.sex}}</div>

テンプレートファイルをプリコンパイルします。

$ handlebars test-template.hbs -f test-template.js

それをhtmlに記述します。

使うjavascriptはhandlebars.jsでもhandlebars.runtime.jsでもどちらでも大丈夫です。


test.html

<div id="output">

<script type="text/javascript" src="./bower_components/jquery/dist/jquery.min.js"></script>
<script type="text/javascript" src="./bower_components/handlebars/handlebars.runtime.min.js"></script>
<script type="text/javascript" src="./test-template.js"></script>
<script type="text/javascript">
var html = Handlebars.templates['test-template.hbs']({
person : {
name: "Satoshi",
age : 33,
sex : 'M'
}
});
$('#output').html(html);
</script>

これにより、以下が出力されます。

<div id="output">

<div>Satoshi</div>
<div>33</div>
<div>M</div>
</div>

ここはGruntで自動化できそうですね。

grunt-contrib-handlebarsを使いましょう。


API

Handlbars.xxx のようなメソッドはいくつかあるので、

http://handlebarsjs.com/reference.html

を参照してください。