「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)でおしまいです。