jQuery Templateについてちょっと調べてみた

先日CSSNite LP18に参加したのですが、中でも一際気になったjQuery Templateの機能を掘り下げたいと思います。

jQuery Template?

利点

これを使うと何が嬉しいかというと、表示のためのHTMLとロジック処理のためのJacaScriptをきちんと分離出来るということが挙げられます。 (※ちなみに、まだbetaです)

サンプル

例えば、こんなHTMLがあったとします。 サーバーサイドからある書籍のリストをAjaxでロードしてリスト表示します。

<div>
    <h4>書籍タイトル</h4>
    <dl id="bookList">
    <!--
    	<dt>逆襲ノマド</dt>
    	<dd>新しい仕事</dd>
        <dt>黄昏サスペンデッド</dt>
        <dd>今日は早く帰ろう</dd>
        <dt>やる気 not Fount!</dt>
        <dd>ノーコメント</dd>
    -->
    </dl> 
</div>

マークアップをした人はコメントアウトしている箇所をdt+ddの定義リストで表示することを想定しています。

一方JavaScript側ではこのような記述をしているようです。


<script type="text/javascript" src="http://ajax.microsoft.com/ajax/jquery/jquery-1.5.2.js"></script>
<script type="text/javascript">

/*
 *	Ajax処理の結果
*/
var result = [
		{ "title":'逆襲ノマド',               "description": '新しい仕事' 	},
		{ "title":'黄昏サスペンデッド',   "description": '今日は早く帰ろう'	},
		{ "title":'やる気 not Fount!',    "description": 'ノーコメント'		}
	];

(function($){
	$( "#load" ).click(function(e){
		
		//result = Ajax処理の結果とか
		var jsonAray = result;

		var bookList = "";
		for (var i = 0; i < jsonAray.length; i ++) {
			var book = jsonAray[i];
			bookList += "<tr>";
			bookList += "<td>" + book.title + "</td>";
			bookList += "<td>" + book.description + "</td>";
			bookList += "</tr>";
		}

		$("#bookList").append( bookList );
	});
})(jQuery);
</script>

定義リストを(dl要素)想定しているのにテーブルのtr要素で返って来ました。
これは、はなから構築するHTMLをちゃんと打ち合わせしていないので例が悪いですが、JavaScriptのロジック中に要素を直書きしているのが原因です。
dt+dd要素にspan要素を追加してidを振り、一つずつ値を設定すれば、JacaScriptの処理中にhtmlタグを記述せずに済みそうですが数が多くなると大変です。

また、後からこの書籍の定義リストをやはりtable要素に変更したいという事になったとします。

これぐらいの規模ならさっと変更箇所を探せますが、複雑な処理を行なっているJavaScriptのコードにポツンとdt+dd要素があったりして、どの部分のコードなのかが分からなかったりします。

そこで、jQuery Templateを使ってこのようにHTMLを記述します。


<div>

   	<h4>書籍タイトル</h4>

    <dl id="bookList2">
    <script id="bookList2Tmpl" type="text/x-jquery-tmpl">
		<dt>${title}</dt>
		<dd>${description}</dd>	
	</script>
	</dl>
</div>

dt+dd要素をhtml側に記述しているのがわかります。

使い方としては script要素の type属性 に "text/x-jquery-tmpl"を記述し、idを振ります。
Ajaxで取得することが予想される書籍リストの情報、Jsonオブジェクト(オブジェクトリテラル)のプロパティ(今回は${title}や${description})を記述しておきます。

Ajaxで取得したデータをテンプレート(id="bookListTemple")に割り当てるJavaScriptのコードはこのようになります。


<script type="text/javascript" src="http://ajax.microsoft.com/ajax/jquery/jquery-1.5.2.js"></script>
<script type="text/javascript" src="http://ajax.microsoft.com/ajax/jquery.templates/beta1/jquery.tmpl.js"></script>

<script type="text/javascript">

/*
 *	Ajax処理の結果
*/
var result = [
		{ "title":'逆襲ノマド', 		"description": '新しい仕事' 	},
		{ "title":'黄昏サスペンデッド', "description": '今日は早く帰ろう'	},
		{ "title":'やる気 not Fount!', 	"description": 'ノーコメント'		}
	];

(function($){
	$( "#loadTmpl" ).click(function(e){
		
		// テンプレートの記述場所によっては注意が必要
		// (scriptタグごと消える)
		//$("#bookList2").children().remove();

		//result = Ajax処理の結果とか
		var jsonAray = result;

		var bookList = $( "#bookList2Tmpl").tmpl( jsonAray );
		
		$("#bookList2").append( bookList );

	});
})(jQuery);
</script>

これでJsonデータのプロパティさえしっかり割り当てていれば、デザイン側の編集は簡単に行うことができます。
今回は配列に複数個の書籍データを同じプロパティ名で指定していますが、このあたりは上手く複数個(ループ)処理してくれるようです。

本当はテンプレート内にdl要素を記述できればいいのですが、同一プロパティを複数個割り当てる場合は、子要素のみの記述になりそうです。

また、この例では追加するdl要素内にscriptタグを記述していますが、DOM操作に注意が必要です。

例えば、dl要素内のdt+dd要素をクリアするつもりで


$("#bookList2").children().remove();

と記述すると、dl要素内のscriptも無くなってしまいます。
この場合はちょっと視認性が落ちますが、head内に移動するなどの必要がありそうです。

サンプルデモ

考察

最近、特にJavaScript上からAjaxなどでデータを取ってくる事が多く、しかも構造が複雑になってきているので、jQuery Templeteを上手く使いこなせば相当コードの見通しが良くなると思います。 なにより、表示と処理ロジックが分離出来るということはデザイナーさんと分業する場合に非常に効果的だと思いました。