JavaScriptのテンプレートエンジンHandlebars入門
Handlebarsを知らないという同僚がいたので、まとめてみます。
ただのテンプレートエンジンでデータバインディングとかはないんですが、もし使いどころがあればご参考までに。
基本的には、
に詳しく書いてあるので、そちらを見てください。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
ではちょっと試しに書いてみましょう。
<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
テンプレートファイルを用意します。
<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でもどちらでも大丈夫です。
<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 のようなメソッドはいくつかあるので、
を参照してください。
Discussion