「Lyase.View Ajax指向のシンプルテンプレートエンジン(その3)」まではLyase.Viewの使い方を紹介しました。ここではLyase.Viewをより深く理解するため、Lyase.Viewのソースコードを読みながらその特徴に迫ります。
↓Lyase.Viewがテンプレートの文字列を解析するソースコードです。Lyase.Viewはテンプレートを解析しながら、そのテンプレートをJavaScriptコードに変換するという方法を使っています。
「new Function("context", parsed.join(""))」とあるように、Lyase.Viewは1つのテンプレートの文字列から1つのJavaScript関数を生成します。Functionオブジェクトを使って、動的にJavaScript関数を生成しているのがポイントです。Functionオブジェクトってこういう使い方もあるんですね。詳しくは「Mozilla Developer Center」の「Core JavaScript 1.5 Reference」を見てください。
Lyase.View = {
_cache : {},
parse : function(template, id) {
var self = Lyase.View,parsed = ["var __out=[],render = Lyase.View.render;"]
var tokens = template.split("<%");
for(var i = 0, l = tokens.length; i<l; i++) {
var token = tokens[i];
if(token.indexOf("%>") == -1){
parsed.push(self._string(token));
continue;
}
var parts = token.split("%>");
parsed.push(self[(parts[0].charAt(0) == "=")?"_value":"_code"](parts[0]));
parsed.push(self._string(parts[1]));
}
parsed.push("return __out.join('');");
var templateFunc = new Function("context", parsed.join(""));
if(id) self._cache[id] = templateFunc;
return templateFunc;
},
テンプレートの文字列から生成したFunctionオブジェクトは、テンプレートの識別子に関連付けてキャッシュしています。「using innerHTML(ページ中の要素として)」のときは要素IDを、「using a template file(外部ファイルとして)」のときはファイルパスを識別子に使います。そのため、同じテンプレートを繰り返し使ったとしても、テンプレートを解析するのは1度だけです。ただし例外があり、「using text(JavaScriptの文字列として)」のときはキャッシュされません。
render : function(options, values) {
var self = Lyase.View, template, id;
if(options.text) return self.parse(options.text, null)(values);
if(options.element) var element = $(options.element);
id = (options.file) ? options.file : element.id;
if(self._cache[id]) return self._cache[id](values);
if(options.element) {
template = self._elementTemplate(element);
}else {
template = (new Ajax.Request(options.file,{asynchronous : false})).transport.responseText;
}
return self.parse(template, id)(values);
},
「using a template file(外部ファイルとして)」のときはAjax.Request(prototype.js)を使って、テンプレートを外部ファイルから取得しますが、そのときHTTPサーバ側でエラーが発生しても、そのエラーレスポンスの内容をテンプレートして解釈しています。この振る舞いが許容できないときは、1例として次のようにソースコードを改良してエラーが発生したときの振る舞いを追加するとよいでしょう。
var request = new Ajax.Request(options.file, {asynchronous : false}).transport;
template = request.status!=200
? '...'
: request.responseText;
Lyase.Viewの紹介は今回(その4)でおしまいです。