Asial Blog

Recruit! Asialで一緒に働きませんか?

手軽にレンダリング!テンプレートエンジンTransparency

カテゴリ :
フロントエンド(HTML5)
タグ :
HTML5
JavaScript

はじめに


Transparencyは、Javascriptで記述されたテンプレートエンジンです。クライアント側にて機能します。このテンプレートエンジンは以下の特徴を持っています

  • テンプレートをHTMLの一部として記述(DOM構造内に記述)
  • 属性値に基づくデータの結合(<%= foo %>や{{foo}}などは不要)
  • 繰り返し構造の描画(ループ処理の記述不要)


一般的なJavaScriptテンプレートエンジン(Underscore.js、Mustache、jQuery Templateなど)では、テンプレートをSCRIPTタグ内に記述します。レンダリング時にはテンプレートからHTML文字列を生成します。これらのエンジンを使った場合、HTMLファイルを編集しずらかったり、読み込みが遅れて画面がブレることが多々あります。

一方で、Transparencyを使うと、HTMLを編集しやすい上、レンダリングを直感的かつ手軽に行えます。特に、jQueryやZeptoと併せて使うと効果的です。この記事ではjQueryと組み合わせた場合の使い方をご紹介します。

Transparencyが対応しているブラウザは、IE9以上、Chrome、Firefox、iOSやAndroidのモバイルブラウザとなります。ただし、jQueryと組み合わせると古いブラウザにも対応できるそうです。

初歩的な使い方


最初に、jQuery経由でテンプレートエンジンを使えるように設定しましょう。jQueryとTransparencyのソースコードを読み込んだ後に、以下のコードを実行します。

  1. $.fn.render = Transparency.jQueryPlugin;

これでjQueryのDOM経由、render()メソッドでレンダリングできるようになります。例えば、次のようになります。まずはテンプレートをHTML内に記述しておきます。

  1. <div id="test">
  2.   <span class="hoge"></span>
  3.   <span data-bind="fuga"></span>
  4. </div>

DOMContentLoadedの後にJavaScriptで以下のコードを実行します。

  1. $('#test').render({
  2.   hoge: 'ホゲ',
  3.   fuga: 'フガ'
  4. });

すると、上記のテンプレート部分(HTML内部)が以下のように更新されます。

  1. <div id="test">
  2.   <span class="hoge">ホゲ</span>
  3.   <span data-bind="fuga">フガ</span>
  4. </div>

このように実行コードは非常にシンプルです。もちろん、HTMLタグはエスケープした状態で表示してくれます。

データ結合


上述のように、Transparencyでは、ある条件に合致する要素にJSONデータを入れ、その要素を更新していきます。その条件とは、JSONのキー値が、以下のいずれかの値と一致することです。

  • 要素のid名
  • 要素のclass名
  • INPUTタグなどのname属性値
  • data-bind属性値


ただ、デフォルトのまま使用することはお勧めできません。なぜならば、テンプレート機能と、CSSや入力フォームの内容が強く依存してしまうからです。出来ることなら、これらの内容を分けた方がコードがスッキリとします。

お勧めは、data-bind属性値のみを参照してデータ結合を行うように設定することです。その設定は次のようにします。これだけで、data-bind属性値とJSONキー値の一致のみがレンダリングの条件となります。

  1. Transparency.matcher = function(element, key) {
  2.   return element.el.getAttribute('data-bind') === key;
  3. };

繰り返し構造


また、繰り返し構造も簡単に実現できます。以下のテンプレート、JavaScriptコード、出力結果を見て下さい。他の実行方法もありますが、以下の方法が最も理解しやすいと思います。

Tempalte
  1. <ul id="keywords">
  2.   <li data-bind="keyword"></li>
  3. </ul>

JavaScript
  1. var keywords = [
  2.   {keyword: 'Asial'},
  3.   {keyword: 'アシアル'},
  4.   {keyword: 'あしある'}
  5. ];
  6.  
  7. $('#keywords').render(keywords);

結果
  1. <ul id="keywords">
  2.   <li data-bind="keyword">Asial</li>
  3.   <li data-bind="keyword">アシアル</li>
  4.   <li data-bind="keyword">あしある</li>
  5. </ul>

Directivesの活用


さらに、出力時に変数を合成したり、タグの属性値を追加することも可能です。これらの場合には、Directivesという機能を使用します。render()メソッドの第二引数にオブジェクトリテラルを渡します。

Template
  1. <div id="person">
  2.   <div data-bind="name"></div>
  3.   <div data-bind="company"></div>
  4. </div>

JavaScript
  1. var data, directives;
  2. data = {
  3.   'id': 10,
  4.   'firstName': 'Kazushi',
  5.   'lastName' : 'Igawa',
  6.   'company': 'Asial'
  7. };
  8.  
  9. directives = {
  10.   name: {
  11.     // data-bind="name"の要素内に出力する内容
  12.     text: function() {
  13.       return this.firstName + ' ' + this.lastName;
  14.     },
  15.     // data-id="name"の要素にdata-id属性を追加
  16.     'data-id': function() {
  17.       return this.id;
  18.     }
  19.   }
  20. };
  21.  
  22. $('#person').render(data, directives);

結果
  1. <div id="person">
  2.   <div data-bind="name" data-id="10">Kazushi Igawa</div>
  3.   <div data-bind="company">Asial</div>
  4. </div>

renderメソッドの第三引数にオプションを渡すことで、デバッグ情報をコンソールに表示してくれます。

  1. $('...').render(data, directives, {debug: true});

まとめ


このようにTransparencyを使うと、HTML内にテンプレートを記述しつつ、手軽にレンダリングを実行できます。また、HTMLタグやCSSと、データやJavaScriptコードをきれいに分離することもできます。とても便利ですので、興味があればぜひ使ってみてください。

ちなみに、類似のテンプレートエンジンもいくつか存在します。以下、参考までに。



参考コード


  1. <!DOCTYPE html>
  2. <html>
  3.   <head>
  4.     <meta charset="utf-8" />
  5.     <script src="http://code.jquery.com/jquery-1.9.1.min.js"></script>
  6.     <script src="https://raw.github.com/leonidas/transparency/master/dist/transparency.min.js"></script>
  7.     <script>
  8.       $.fn.render = Transparency.jQueryPlugin;
  9.       
  10.       Transparency.matcher = function(element, key) {
  11.         return element.el.getAttribute('data-bind') === key;
  12.       };
  13.       
  14.       $(function() {
  15.         // 最初の例
  16.         var data1 = {
  17.           hoge: 'ホゲ',
  18.           fuga: 'フガ'
  19.         };
  20.  
  21.         $('#test').render(data1);
  22.         
  23.         // 次の例
  24.         var keywords = [
  25.           {keyword: 'Asial'},
  26.           {keyword: 'アシアル'},
  27.           {keyword: 'あしある'}
  28.         ];
  29.  
  30.         $('#keywords').render(keywords);
  31.         
  32.         // 最後の例
  33.         var data2, directives;
  34.         data2 = {
  35.           'id': 10,
  36.           'firstName': 'Kazushi',
  37.           'lastName' : 'Igawa',
  38.           'company': 'Asial'
  39.         };
  40.  
  41.         directives = {
  42.           name: {
  43.             text: function() {
  44.               return this.firstName + ' ' + this.lastName;
  45.             },
  46.             'data-id': function() {
  47.               return this.id;
  48.             }
  49.           }
  50.         };
  51.  
  52.         $('#person').render(data2, directives);
  53.       });
  54.     </script>
  55.   </head>
  56.   <body>
  57.     <div id="test">
  58.       <span data-bind="hoge"></span>
  59.       <span data-bind="fuga"></span>
  60.     </div>
  61.     <ul id="keywords">
  62.       <li data-bind="keyword"></li>
  63.     </ul>
  64.     <div id="person">
  65.       <div data-bind="name"></div>
  66.       <div data-bind="company"></div>
  67.     </div>
  68.   </body>
  69. </html>