我一直在使用一個小工具,並發現它在構建Javascript應用過程中非常實用。它是一個非常簡單的模板函數,速度快,支持緩存,並容易使用。我想分享一下使用它的過程中的一些技巧。
以下是模板函數的代碼(你可以從正要出版的Secrets of the JavaScript Ninja一書中得到更精煉的版本):
// 簡單JavaScript模板引擎
// John Resig - http://ejohn.org/ - MIT Licensed
(function(){
var cache = {};
this.tmpl = function tmpl(str, data){
// 判斷我們是否已經有這麼一個模板,或者我們需要載入模板
// 並保證把結果保存到緩存中。
var fn = !/\W/.test(str) ?
cache[str] = cache[str] ||
tmpl(document.getElementById(str).innerHTML) :
// 生成一個可重用的函數,用於提供模板生成功能
// (它會被記錄到緩存內).
new Function("obj",
"var p=[],print=function(){p.push.apply(p,arguments);};" +
// 通過with(){}把數據作為本地變量引入
"with(obj){p.push('" +
// 把模板轉換未純javascript代碼
str
.replace(/[\r\t\n]/g, " ")
.split("<%").join("\t")
.replace(/((^|%>)[^\t]*)'/g, "$1\r")
.replace(/\t=(.*?)%>/g, "',$1,'")
.split("\t").join("');")
.split("%>").join("p.push('")
.split("\r").join("\\'")
+ "');}return p.join('');");
// 給用戶提供一些基本的柯裡化功能
return data ? fn( data ) : fn;
};
})();
你的模板代碼看起來將是類似於(這並不是規定的格式,但是我比較喜歡這樣):
<script type="text/html" id="item_tmpl"> <div id="<%=id%>" class="<%=(i % 2 == 1 ? " even" : "")%>"> <div class="grid_1 alpha right"> <img class="righted" src="<%=profile_image_url%>"/> </div> <div class="grid_6 omega contents"> <p><b><a href="/<%=from_user%>"><%=from_user%></a>:</b> <%=text%></p> </div> </div> </script>
你也可以內嵌腳本:
<script type="text/html" id="user_tmpl">
<% for ( var i = 0; i < users.length; i++ ) { %>
<li><a href="<%=users[i].url%>"><%=users[i].name%></a></li>
<% } %>
</script>
提示:把腳本內嵌到你的頁面中,並且content-type是未知的(例如在這個例子中,浏覽器不知道該如何執行 text/html 腳本),那麼浏覽器會把它忽略掉 - 同時搜索引擎和屏幕讀取也會忽略掉它。這是一個非常好的偽裝代碼,可以把你的模板嵌入到你的頁面中。我喜歡使用快速卻又隨性的技術,我只需一到兩個小模板,就可以得到又輕型和快速應用。
你可以在腳本中,像這樣去使用:
var results = document.getElementById("results");
results.innerHTML = tmpl("item_tmpl", dataObject);
你可以預編譯結果,在稍後使用。如果你只使用一個ID作為參數(或者一個模板代碼)來調用模板函數,那麼它就會返回一個預編譯的函數,你就可以在稍後調用:
var show_user = tmpl("item_tmpl"), html = "";
for ( var i = 0; i < users.length; i++ ) {
html += show_user( users[i] );
}
這是目前最沒辦法的辦法,解析和轉換代碼——對這你很可能無愛。不過他只有我中意的一項技術:在字符串中用字符靜態搜索和靜態替換時,比如split("match").join("replace"),執行速度更好——看起來不直觀但可以有效工作在現代浏覽器裡(下一版FireFox會大幅提高replace(/match/g,"replace")的性能——所以現在這樣的長表達式以後不需要的)
放輕松享受它——我很好奇代碼中的突變。即使它很簡單,仍然有很多事情可以用它做。