4行代碼實現js模板引擎

在平時編碼中,常常要作拼接字符串的工做,如把json數據用HTML展現出來,以往字符串拼接與邏輯混在在一塊兒會讓代碼晦澀不堪,加大了多人協做與維護的成本。而採用前端模板機制就能很好的解決這個問題。javascript

 

精妙的 tmplcss

 

前端模板類開源的很多,但最屬 jQuery 做者 John Resig 開發的 「javascript micro templating」 最爲精妙,寥寥幾筆便實現了模板引擎核心功能。 它的介紹與使用方式請看做者博客:http://ejohn.org/blog/javascript-micro-templating/html

 

麻雀雖小,五臟俱全,除了基本的數據附加外,還擁有緩存機制、邏輯支持。如今,若要我評出一個javascript 最節能的自定義函數排名,第一名是 $ 函數(document.getElementById 簡版),而第二名就是 tmpl 了。前端

 

固然,它並不是完美,我使用過程當中發現了一些問題:java

 

tmpl 美中不足git

 

    1、沒法正確處理轉義字符,如: tmpl('<%=name%>\\<%=id%> ', {name:'糖餅', id: '1987'});它就會報錯。若正常工做,它應該輸出:糖餅\1987github

 

    2、沒法識別數據裏的單引號web

 

    3、設置變量默認值複雜,如正則表達式

 

           tmpl('<%if(obj.name){%><%=name%><%}else{%>默認值<%}%> ', {name:'糖餅'});  //設置name默認爲 「默認值」json

tmpl 優化版本

廢話很少說,先敬上代碼:

 

 1 function tmpl(str, data) {
 2     var $ = '$' + (+ new Date)
 3         , fn = function (data) {
 4         var i, variable = [$], value = [[]];
 5         for (i in data) {
 6             variable.push(i);
 7             value.push(data[i]);
 8         }
 9         return (new Function(variable, fn.$))
10             .apply(data, value).join("");
11     };
12 
13     //將模板解析成函數
14     fn.$ = fn.$ || $ + ".push('"
15         + str.replace(/\\/g, "\\\\")
16             .replace(/'/g, "\\'")  //防止單括號錯誤
17             .replace(/[\r\t\n]/g, " ")
18             .split("[:").join("\t")
19             .replace(/((^|:])[^\t]*)'/g, "$1\r")
20             .replace(/\t=([^\?]*?):]/g, "',$1,'")
21             .replace(/\t=([^\?]*?)\?(.*?):]/g, "',this.$1||'$2','")   //  [:=data?:]  [:=data?任何內容:]
22             .split("\t").join("');")
23             .split(":]").join($ + ".push('")
24             .split("\r").join("\\'")
25         + "');return " + $;
26 
27     //若是未定義data則返回編譯好的函數,使用時直接傳入數據便可,
28     //省去每次解析成函數的時間
29     return data ? fn(data) : fn;
30 
31 };    

好吧,上面的代碼看起來超出了4行,原諒我標題黨。不過這段代碼通過壓縮後,確實只有四行^_^。下面咱們就來詳細解構它。

首先看一下使用示例:

 1 //循環結構
 2 
 3 var tpl = '[: for(var k in ary){ var one=ary[k]; :]'
 4         + '<p>[:=one:]</p>'
 5         + '[: } :]';
 6 var data = {ary:[123,'abc']};
 8 var div = tmpl(tpl,data);
10 console.log(div); //</p>123</p><p>abc</p>
11 
12 
13 //變量驗證
14 
15 var tpl = '[: if(this.name!==undefined){ :]' //注意必須使用 this.name,直接使用name,若是未定義就會報錯
16 + '<p>[:=name:]</p>'
17 + '[: } :]';
18 var data = {name:'abc'};
20 var div = tmpl(tpl,data);
22 
23 //你還能夠這樣方便地使用未定義的變量: 24
25 var tpl = '<p>name:[:=name?:], name:[:=name?默認值:]</p>'; 26 var data = {no:'abc'}; 27 var div = tmpl(tpl,data); 28 29 console.log(div); // <p>name:, name:默認值</p> 30 31 32 //緩存編譯結果 33 34 35 var tpl = '[: for(var k in ary){ var one=ary[k]; :]' 36 + '<p>[:=one:]</p>' 37 + '[: } :]'; 38 var data = {ary:[123,'abc']}; 40 var render = tmpl(tpl); //不傳入data,則生成緩存,屢次使用緩存節約大量正則運算 42 var div = render(data); //傳入data,代入變量,解析成最終結果 43 44 console.log(div); //<p>123</p><p>abc</p>

使用方法:在 [: 與 :] 之間使用任何js代碼,而且經過 [:=data:] 方式以字符串形式輸出變量。更加詳細的使用方法/手冊,請查看:http://docs.codekart.jojoin.com/p/tool_tmpl

優化的地方:

    一. 正確處理轉義字符 \ ' 等轉義字符

    二. 修改包裹符 <% %> 爲 [: :] 防止與 html標籤</>和求餘運算符%產生衝突。

    三. 修改環境變量 obj 爲 this

         tmpl('<%if(obj.name=="name")%>')   //舊版本

         tmpl('[: if(this.name=="name") :]')   //新版本

    四. 爲變量添加默認值

         tmpl('<%if(obj.name){%><%=name%><%}else{%>默認值<%}%>')   //舊版本

         tmpl('[:=name?默認值:]')   //新版本

    五. 去掉 with 語句,大幅提高引擎性能

    六. 刪除無關緊要的功能,保持精簡

    七. 增長調試模式

        //打印模板編譯中間結果:

        console(tmpl('<p>[:=name:]</p>').$); 

        //$1408707567855.push('<p>',name,'</p>');return $1408707567855

此引擎函數大體分爲兩部分:

    一. 上半部分:模板函數解析執行

    二. 下半部分:正則運算生成模板函數

能夠看出,引擎實現的重點主要在下半部分的一堆正則表達式,也就是「模板編譯」的過程。這裏我不打算把每個正則的功能都說清楚,那樣篇幅太大(好吧是我懶),各位看官請自行閱讀研究。

另外,此模板引擎已被集成到 Node.js web開發框架 Codekart 中。

Codekart 是一套給 Node.js 開發者使用的應用程序開發框架和工具包。 它提供一套豐富的標準庫以及簡單的接口和邏輯結構, 其目的是使開發人員更快速地進行項目開發。 使用 Codekart 能夠減小代碼的編寫量, 並將你的精力投入到項目的創造性開發上。

它已經幫你出色的完成了下面這些事情:

優雅的框架思惟

若是你須要一個真正的框架,而不是一個模塊/中間件/工具箱,若是你須要簡約與便捷,須要一目瞭然、理所固然的溫馨感,那麼 Codekart 將是最好的選擇。

高性能 HTTP 服務器

Codekart 處理 http 請求的性能接近原生 Node.js 代碼: http.createServer(), 緣由是框架只是對此函數作了簡單的封裝,其性能的損耗僅僅只有一個 url 正則匹配運算,路由請求處理程序。

便捷的靜態文件服務器

把文件放入 static/ 目錄下,啓動Codekart,url 訪問,搞定!

web 頁面模塊化支持

實際上,這是Codekart最出色的部分!它是先後端一體化的,能夠像寫配置文件同樣編寫web頁面, 框架自動完成 js、css 、tpl 文件的模塊化加載、合併、壓縮, 並在html裏引用,自動完成 html 模板的解析,而且支持頁面繼承和多態,一切就是那麼簡單輕鬆!

豐富的工具箱

Codekart 準備了一系列強大的先後端工具集合,涉及進程通訊,數據緩存,文件讀取,文件上傳,數據採集與處理,流程控制,任務計劃等諸多方面。

框架源碼託管在Github:https://github.com/yangjiePro/Codekart   歡迎提交新的代碼!

相關文章
相關標籤/搜索