2014年11月5日水曜日

【JsRender】prop

株式会社ジェニシス 技術開発事業部の遠藤 太志郎(Tacy)です。

現在はJavaScriptによる画面レンダリングツール「JsRender」について連載しています。

今回は「props」、つまり「プロパティ」についてご紹介します。

要するにMap

このpropsとは、要するにJavaで言えばMap総当たりのことです。
propsは「Mapに格納されている全てのkeyに対して値を取得する」というものです。

例を挙げてみましょう。

まず以下にまたしてもメンバー情報一覧を表示するソースを記載します。

<script id="jsRenderTmpl" type="text/x-jsrender">
★{{:title}}
<table>
 <tr>
  <td>名前</td>
  <td>年齢</td>
  <td>性別</td>
  <td>血液型</td>
 </tr>
{{for members}}

<tr>
 <td>{{:name}}</td>
 <td>{{:age}}</td>
 <td>{{:sex}}</td>
 <td>{{:blood}}</td>
</tr>

{{/for}}

</table>
</script>

<script>
var data = {
  "title": "名前一覧",
  "members": [
      {"name": "Tacy1号","age": "28","sex": "男","blood": "AB"},
      {"name": "Tacy2号","age": "28","sex": "男","blood": "AB"},
      {"name": "Tacy17号","age": "28","sex": "男","blood": "AB"}
 ]
};

var template = $.templates("#jsRenderTmpl");

var htmlOutput = template.render(data);

$("#result").html(htmlOutput);
</script>



今回問題になるのは「横の長さ」です。
サンプルでは「名前」「年齢」「性別」「血液型」の4列ですけれども、案件によってはズラッと長々と出てくることもありますので、そういう場合に一つ一つペタペタ書いていくのは結構大変というもの。

そこで、「JSONタグの中にあるものを全て出力する」としたい場合に出番となるのがpropsです。

そのサンプルがこちら。

<script id="jsRenderTmpl" type="text/x-jsrender">
★{{:title}}
<table>
{{props members}}
<tr>
 {{props prop}}
 <td>{{>key}}:{{>prop}}</td>
 {{/props}}
</tr>
{{/props}}

</table>
</script>

<script>
var data = {
  "title": "名前一覧",
  "members": [
      {"seq":0,"name": "Tacy1号","age": "28","sex": "男","blood": "AB"},
      {"seq":1,"name": "Tacy2号","age": "28","sex": "男","blood": "AB"},
      {"seq":2,"name": "Tacy3号","age": "28","sex": "男","blood": "AB"}
 ]
};

var template = $.templates("#jsRenderTmpl");

var htmlOutput = template.render(data);

$("#result").html(htmlOutput);
</script>



「{{props members}}」とやることで、menbersの中の情報を全部取得します。
ここから、


  • 「{{>key}}」でそのパラメータのキー値を。(配列の場合はシーケンス番号)
  • 「{{>prop}}」と指定することそのパラメータを。


これらをループで取得することが出来るわけです。

propsは入れ子で使うことも可能で、上記の例も入れ子型です。
「{{props prop}}」となっている部分が入れ子に書いている部分ですね。

デザインが……

「あれ? 上と下で画面レイアウトが違うじゃねえか!!」とお気づきの方、その通りです。

propsはパラメータ総出力なので、細かいレイアウト調整が効かないのです。
なので「ヘッダーを日本語で追加したい」とか「JSONタグのうち、必要なカラムだけ出す」とか、
そういう細かい要望にはif文でも使わない限り対応出来ません。

そんなロジック入れるのであれば、最初から従来のやり方通りにkey値をペタペタ決め打ちして、for文で回して書いていった方が良いと思いますね。

需要としては「JSONタグの中身をシンプルに全部出す」というケースくらいしか無いでしょう。

JSONタグを合わせる

「加工無しの全出力なんて、デバッグでしか使わないよ!!」と思ってしまうかもしれませんが、
しかしですね、この問題は発想の転換で乗り切りましょう。
ズバリ、JsRender側ではなく、JSONタグの方を合わせる方法で解決出来ます。

「サーバ側処理で必要なデータ加工を全て完了させて、HTML側ではそれを出すだけ」という切り分けを徹底すれば、
非常に便利な機能になります。

こんな感じに。


<script id="jsRenderTmpl" type="text/x-jsrender">
★{{:title}}
<table>
<tr>
 {{props header}}
 <td>{{>prop}}</td>
 {{/props}}
</tr>
{{props members}}
<tr>
 {{props prop}}
 <td>{{>prop}}</td>
 {{/props}}
</tr>
{{/props}}

</table>
</script>

<script>
var data = {
  "title": "名前一覧",
  "header": {"seq":"No","name": "名前","age": "年齢","sex": "性別","blood": "血液型"},
  "members": [
      {"seq":0,"name": "Tacy1号","age": "28","sex": "男","blood": "AB"},
      {"seq":1,"name": "Tacy2号","age": "28","sex": "男","blood": "AB"},
      {"seq":2,"name": "Tacy3号","age": "28","sex": "男","blood": "AB"}
 ]
};

var template = $.templates("#jsRenderTmpl");

var htmlOutput = template.render(data);

$("#result").html(htmlOutput);
</script>


ほら?
ヘッダーの属性とかも全部ひっ包めてJSONに入れてしまえばキッチリ綺麗になるでしょ?

これはコーディング思想として一つの基準になると思いますね。
HTMLやJavaScriptにボコボコ書き過ぎてしまうと可読性や生産性が大幅に下がります。

JsRenderは確かに便利なライブラリですが、しかしJsRenderは重い処理をする為にあるのではないのです。
「必要な情報はJSONに全部入れる」という実装思想を持つことが良いモジュールを作るキーとなるでしょう。

終わりに

引き続きJsRenderについて連載を継続します。