3つの簡単便利Javascriptテンプレートエンジン。Mustache.js, Handlebars.js, Microtemplating
.多忙きわまりない2013年初夏でございます。
最近あんまりコードらしいもの書けてなくって、vagrantとかshefとかpjaxとかnodeとか理解するために時間つくりたい、コード書きたい!ってなってます。今回ちょっとajaxまわりのものの実装でjavascriptのテンプレートエンジンに調べる必要あったので、javascriptのテンプレートエンジンに触れてみようかなと。
phpのテンプレートだとsmartyだとか、rubyだとERBとかなんかそういうのですけど、javascriptのテンプレートエンジンについて知らなかったんで。
目次 – Table of Contents
Javascriptのテンプレートエンジンの候補
はじめに申し上げますが、いっぱいあります。ここみるといいです。
癖とかいろいろあって、今回選んだのは3つ(内2つはほとんど似ている)
- Microtemplating
(すごく軽くて、すごく手軽で、すごく早い。作者はjQueryのリードプログラマーだって。はい、すごい。) - Mustache.js
(Mustacheの書き方を覚えたらたら、いろんな言語でMustache使えますよ。便利ですよっていうやつ。開発者はgithubのcofounder。はい、すごい、すごい。
ただ、Mustacheだとif文だとかロジックを入れたい場合には非力なため、Mustacheと互換性のあってロジック部分も強化できるhandlebars.jsというものを使う。)
その他候補にあがったのは、
- pure.js
(書き方に癖があるし、雛形となるDOMが生成してある必要があるっぽいので、Ajaxの動的生成には向かないのかな?ということで、今回パス) - underscore.js
(Ruby使いな人にとってはunderscore.jsでよかったりするのかな。今回は手をだせなかった。) - JsRender
(簡単そうでjQuery無しで動くけど30kと重い。殆どの場合jQuery導入してるから恩恵がない。ただ、jQueryの本命テンプレートエンジンとして開発されてるっぽいので、jQuery版リリースされたら導入を検討しようかと思ったり。)
(ごく数名の天才エンジニアが提供してくれてるライブラリのおかげで、ほとんどのwebサービスがつくられてるんだなと感じます。)
1. John Resig氏のJavaScript Micro-Templating
いや、すごいです。サイズ1k。手軽、軽い、早い。三拍子そろってます。作者はjQueryの中の人の一人のようです。javascript Ninjaっていう本出版されてるようで、ソース理解しようとしましたがむずかしい。2行目のMIT Licensed.って文字以降、眠たくなったので読む努力をやめました。
さて、MITライセンスなので、ありがたやと感謝しながらこちらの作者ご本人のブログのソースを丸々つかわせてもらいます。(2008年の記事ですが、5年経った今、現役で使わせてもらいます・・・)
出力先を準備
HTMLで結果を出力する箇所に任意のidを指定する。
</pre> <ul id="results">ここに出力</ul> <pre>
置換用のJSONデータを準備
今回こんな感じのデータ群を用意しました。
var dataObject = { members:[ {id:1, name:"hoge", text:"aaaaaaaaaaaaaa"}, {id:9, name:"fuga", text:"bbbbbbbbbbbbbb"}, {id:15, name:"hoge", text:"cccccccccccccc"}, {id:22, name:"fuga", text:"dddddddddddddd"}, {id:78, name:"hoge", text:"eeeeeeeeeeeeee"}, {id:876, name:"fuga", text:"ffffffffffffff"}, {id:1033, name:"hoge", text:"gggggggggggggg"}, {id:7899, name:"fuga", text:"hhhhhhhhhhhhhh"} ] }; // -> End of dataObject
テンプレートを準備
ポイント
- type=”text/html”とすることでHTMLとして解釈させる。idも指定。(ここでは、item_tmplと指定しました。)
- <% ●● %> ←ここにjavascriptの構文、ifだとかfor文だとか書けるようです。
- <%= ■■ %> ←出力したい変数
<script id="item_tmpl" type="text/html">// <![CDATA[ <% for ( var i = 0; i < members.length; i++ ) { %> <li id="<%=members[i].id%>" class="<%=(i % 2 == 1 ? " even" : " odd")%>"> <%=i+1%>人目 <%=members[i].text%> (from <%=members[i].name%>[ID:<%=members[i].id%>])</li> <% } %> // ]]></script>
もう、なんか、したい放題ですね。導入しやすい。
実行コード
こんな感じ。
var results = document.getElementById("results"); // tmpl(テンプレートのID, データ群) results.innerHTML = tmpl("item_tmpl", dataObject);
DEMO
というわけで完成しましたので動作デモ。(jsFiddle便利ですね。)
2. Mustache.js か Handlebars.js
さて、今度はちょっと今風(謎)。サーバサイドのjavascriptでも使えるようですね。 github作った人の一人が書いたテンプレートエンジン Mustache.js。(余談ですが、github作ったってことだから、pjaxのライブラリもgithubに公開されてて、やっぱりと思った。) Mustache.jsの強みが「Logic-less templates.」とあるとおり、ロジック部分がかなり省略されてます。ので、条件分岐なんかをテンプレート側で行えないので、ロジックを組み込みたい場合は、Mustache.jsと互換性のあるHandlebars.jsを使うことになるようです。 なので、今回は「Handlebars.js」の使用して、先のデモと同じ事を行うサンプルです。
JSファイルの読み込み。
今回、こちらのCDNを使おうかな。 //cdnjs.cloudflare.com/ajax/libs/handlebars.js/1.0.0/handlebars.min.js あとjQueryも読み込んでおこうかな。
HTMLとJSONデータを用意
この手順はMicro-Templatingと同じ。
</pre> <ul id="results">ここに出力</ul> <pre>
var dataObject = { members:[ {id:1, name:"hoge", text:"aaaaaaaaaaaaaa"}, {id:9, name:"fuga", text:"bbbbbbbbbbbbbb"}, {id:15, name:"hoge", text:"cccccccccccccc"}, {id:22, name:"fuga", text:"dddddddddddddd"}, {id:78, name:"hoge", text:"eeeeeeeeeeeeee"}, {id:876, name:"fuga", text:"ffffffffffffff"}, {id:1033, name:"hoge", text:"gggggggggggggg"}, {id:7899, name:"fuga", text:"hhhhhhhhhhhhhh"} ] }; // -> End of dataObject
テンプレートの用意
ここからMicro-Templatingとは異なってきます。
ポイント
- {{変数}}で、変数出力します。
- {{#●●●●●}}….{{/●●●●●}}で、自動的にメンバー分、ループします。
- ループ中に{{@index}}でインデックスナンバーを取得できます。{{@index}}のかわりに{{@key}}とかも使えるようです。
- classの所、{{addclasses @index}}については後述
それ以外の文法はドキュメントを参照するか、直感で感じて下さい。
<script id="item_tmpl" type="text/x-handlebars-template">// <![CDATA[ {{#members}} <li id="{{id}}" class="{{addclasses @index}}"> {{@index}}人目 {{text}} (from {{name}}[ID:{{id}}])</li> {{/members}} // ]]></script>
ロジック部分
上述の{{addclasses @index}}の部分ですが、
奇数回の場合はodd、偶数回の場合はevenを付与するために、このロジック部分ののヘルパーを用意します。
addclassesは任意のヘルパー名、@indexは渡したい引数で、ここではループのインデックス番号を渡してます。
// クラスを追加するためのヘルパー(偶数奇数を調べて、class付与。) Handlebars.registerHelper('addclasses', function(num) { return (num % 2 == 1) ? "even" : "odd"; });
実行
最後は実行です。
// テンプレートを取得して、データ反映。 var tpl_source = $("#item_tmpl").html(); var h = Handlebars.compile(tpl_source); var content = h(dataObject); // 出力 var results = document.getElementById("results"); results.innerHTML = content;
DEMO
動作デモです。(jsFiddle便利)
Conclusion
とにかく、気軽に使いたかったら、Micro-Templatingかなと。
Handlebars.jsだと、ロジック部分、簡易なものでも書き方が複雑になっちゃう。逆にかなり複雑なロジックはいってくるならこっちを選んだほうがいいという感じでしょうか。
あとは、underscore.jsあたりが今風な感じがしてます。今回触れなかったですけど。
他にも、いいのあったら教えて下さい。
参考にしたサイト
今回海外サイトばっかりだった。