“模板”這個詞,可能很多人第一印象是后端的技術(shù)(Smarty,Velocity等),但本文要講的卻不是后端的概念,而是前端開發(fā)中所使用到的一種技術(shù),也就是“前端模板”技術(shù)。
目前創(chuàng)新互聯(lián)已為上1000+的企業(yè)提供了網(wǎng)站建設(shè)、域名、網(wǎng)站空間、網(wǎng)站托管維護、企業(yè)網(wǎng)站設(shè)計、大田網(wǎng)站維護等服務(wù),公司將堅持客戶導向、應(yīng)用為本的策略,正道將秉承"和諧、參與、激情"的文化,與客戶和合作伙伴齊心協(xié)力一起成長,共同發(fā)展。
模板的工作原理可以簡單地分成兩個步驟:模板解析(翻譯)和數(shù)據(jù)渲染。這兩個步驟可分別部署在前端或后端來執(zhí)行。如果都放在后端執(zhí)行,則是像Smarty這樣的后端模板,而如果都放在前端來執(zhí)行,則是我們要探討的前端模板。
隨著前端交互的復雜性不變提升,無刷新頁面數(shù)據(jù)傳輸與渲染越發(fā)地頻繁化,我們發(fā)現(xiàn)傳統(tǒng)的前端開發(fā)方式在ajax數(shù)據(jù)渲染等方面存在著一個主要問題:繁瑣的數(shù)據(jù)渲染。當前端從后臺通過ajax等方式或許到數(shù)據(jù)后,如果要將這個數(shù)據(jù)渲染到指定的dom元素中,則需要進行各種字符串拼接工作或者一系列創(chuàng)建元素的工作,還不論細節(jié)的問題(單引號雙引號問題等),不管是哪一種形式,都是繁瑣且費時的。同時,在可讀性與維護性上也存在問題。試想,各種循環(huán)操作的字符串拼接,元素創(chuàng)建插入,在需要修改時,都需要重新花費不少時間與精力。那有什么方法可以解決這個問題呢?
當我們在JSP中寫
?
比如我們可以寫一段循環(huán)的li標簽的前端模板語言。通過前端模板引擎轉(zhuǎn)換后成本一連串得li標簽的html語言。這時候就可以直接采用innerHTML方法把html代碼插入到ul對象中,那么就完成了生成ul列表的功能。
?初識??
前端的模板核心是模板解析引擎,而解析引擎的主要作用是將模板語言轉(zhuǎn)換成html/xml格式。不同的前端模板有著不同的模板語言,解析引擎因此也各不相同。讓我們先來認識幾款前端模板,了解下它們各自的模板語言。
Yaya Template是一款輕量級的模板引擎,采用原生javascript語法,具有易學易用等特點。我們來看一段用Yaya Template渲染列表數(shù)據(jù)的實例:
模板語言(通用過for循環(huán),輸出“這是第n列”的li列表)
?
for(var i=0;i {$ } |
??
有了模板語言后,我們只需要將數(shù)據(jù)“打入”模板語言中的”list”,就可以生成我們想要的html/xml格式了。如上例,我們只需要得到這個模板語言進行翻譯,并調(diào)用對應(yīng)的render方法,
?
var list = [“紅桃”,”方塊”,”梅花”,”黑桃”]; var html = YayaTemplate(templateText).render({list:list}); |
??
這個html則是模板引擎轉(zhuǎn)換成的html/xml語言,在上例中,則為:
?
?
從這個例子中,我們可以發(fā)現(xiàn),{$…$}表示輸出的html/xml片段,{%…%}表示輸出javascript變量。得到的html,我們可以用直接作為dom的innerHTML或者其他用處。
這便是前端模板,它使得我們不必去處理字符串拼接等問題,用最直觀的方式來渲染數(shù)據(jù)。我們再來看另外一款前端模板EasyTemplate。還是之前的例子,用EasyTemplate模板寫法如下:
?
<#list data as list> #list> |
??
同樣,需要將實際數(shù)據(jù)替換模板變量,這里采用:
var list = [“紅桃”,”方塊”,”梅花”,”黑桃”]; var html = easyTemplate.render(templateText,list); //templateText指模板語言 |
?像EasyTemplate這樣的前端模板,是屬于自定義模板語言的一種前端模板。我們可以從上例看出,””就是EasyTemplate自定義的循環(huán)條件。像這樣EasyTemplate?模板一樣采用自定義標簽的前端模板還有?lite Template:
?
渲染時采用:
var list = [“紅桃”,”方塊”,”梅花”,”黑桃”]; var html = liteFunction(templateText,’list’)(list); |
?
好了,我們再來看看jquery作者John Resig所寫的一個前端模板jquery template。說真的,它如同jquery一樣,短小精悍。還是老例子:
<% for(var i=0;i <% } %> |
??
渲染采用:
var list = [“紅桃”,”方塊”,”梅花”,”黑桃”]; var html = tmpl(“templateid”, list); |
??我們可以看出,Yaya Template與jquery template在模板語言的寫法上正好相反。前者將輸出html語言做特殊標記{$…$},而后者對javascript語言做特殊標記。這兩種模板已經(jīng)使得學習成本很低了,而接下來介紹的ace template的寫法將更加簡單易懂。
for(var i=0;i } |
??
渲染采用:
var list = [“紅桃”,”方塊”,”梅花”,”黑桃”]; var html = AceTemplate.format(“templateid”, {list:list}); |
?ace template采用了html與js語言直接混搭的風格,在兩者間可以直接的書寫,不用添加任何的標志用以區(qū)分不同的語言。而在html語言里面,使用js變量則采用#{}的方式輸出。ace template之所以可以兼容html與js混合寫法,是通過按行解析來實現(xiàn)的。所以,如果代碼能夠保證html語言與js按行劃分,這樣的用法其實是很方便的。并且ace template值得說明的一點是支持自動編碼防止xss漏洞,通過#{}渲染出來的javascript變量,已經(jīng)經(jīng)過了編碼處理,這一點是很方便的。而對于不需要這個功能,需要原文輸出的時候,ace template也提供了!#{}方法來滿足這種需求。
通過上面對五個前端模板的簡單介紹,我們可以了解到不同前端模板的各種形態(tài),這包括寫法與用法等直觀印象。但我們知道,前端模板的核心是代碼的轉(zhuǎn)換,這肯定是需要轉(zhuǎn)換時間的,那就以上五個不同的前端模板,性能上會有怎樣不同的表現(xiàn)呢。??
前端模板語言到html/xml語言,是通過模板引擎進行翻譯的。而模板引擎的翻譯性能在某種程度上決定了前端模板解決方案的可行性的高低。上訴五種前端模板,各自的性能會是怎么樣的,我們對它們進行測試。分別對Yaya Template、EasyTemplate、jquery template、?ace template、lite template部署前端模板做同樣的操作,比較模板引擎翻譯時間代價。
各自的模板代碼如下:
Yaya Templat?
for (var i=0;i if (i<100){ {$ } else{ {$ } } |
??
EasyTemplate?
<#list data as list> <#if (list_index <100)> <#else> #if> #list> |
??
jquery template?
<% for (var i=0;i <% if (i<100) { %> <% } else{ %> <% } %> <% } %> |
?
ace template?
for (var i=0;i if (i<100){ } else{ } } |
?
lite template?
??
然后我們改變list數(shù)組里面的元素個數(shù),對各個模板翻譯執(zhí)行的時間進行記錄。結(jié)果如下(xp+ie6/ie8/firefox/chrome運行環(huán)境):
模板翻譯時間對比表(第一次翻譯并渲染數(shù)據(jù) 時間單位:毫秒)
?
List長度 | Yaya Template | EasyTemplate | jquery template | ace template | lite template | |
1 | ie6 | 0 0 0 0 | 0 0 0 0 | 0 0 0 0 | 0 0 0 0 | 16 15 12 4 |
ie8 | ||||||
firefox | ||||||
chrome | ||||||
10 | ie6 | 0 0 0 0 | 0 0 0 0 | 0 0 1 0 | 0 0 0 1 | 16 15 11 2 |
ie8 | ||||||
firefox | ||||||
chrome | ||||||
100 | ie6 | 0 0 0 0 | 0 0 0 0 | 0 0 1 1 | 0 0 1 0 | 15 16 10 4 |
ie8 | ||||||
firefox | ||||||
chrome | ||||||
1000 | ie6 | 0 0 1 0 | 16 16 2 3 | 16 0 3 2 | 0 0 2 3 | 15 15 21 7 |
ie8 | ||||||
firefox | ||||||
chrome | ||||||
10000 | ie6 | 63 16 7 4 | 78 47 22 26 | 110 47 27 23 | 62 62 20 22 | 78 31 22 15 |
ie8 | ||||||
firefox | ||||||
chrome | ||||||
100000 | ie6 | 672 250 75 90 | 1719 609 221 304 | 1203 719 267 308 | 750 328 203 288 | 688 250 124 114 |
ie8 | ||||||
firefox | ||||||
chrome |
?
通過第一次翻譯后,如果前端模板可以緩存翻譯后的中間代碼,或者可以返回構(gòu)建中間代碼的函數(shù),那么再次渲染數(shù)據(jù)的時候,就不需要再翻譯。這樣可以極大的縮小渲染數(shù)據(jù)的時間,提高速度。
綜合各種調(diào)研數(shù)據(jù)對比表如下:?
Yaya Template | EasyTemplate | jquery template | ace template | lite template | |
緩存加速 | 有 | 無 | 有 | 有 | 有 |
防xss漏洞編碼 | 無 | 無 | 無 | 有 | 有 |
擴展語法 | 無 | 有 | 無 | 無 | 有 |
錯誤跟蹤 | 無 | 無 | 無 | 無 | 有 |
代碼尺寸(字節(jié)) | 483 | 1527 | 453 | 2512 | 91511 |
?兼容
?前端模板的兼容性也是一個重要的問題。能夠?qū)崿F(xiàn)用戶不同的前端模板需求,將前端模板語言正確翻譯成html/xml語言,是優(yōu)秀的前端模板所需要具備的特點。而通過對以上五種前端模板的測試,并沒有發(fā)現(xiàn)嚴重的兼容性問題。但在一些細節(jié)上,還是發(fā)現(xiàn)了一些問題如下表:
兼容性測試對比表?
測試點 | Yaya Template | EasyTemplate | jquery template | ace template | lite template |
換行空白 | 通過 | 空白被省略 | 通過 | 通過 | 通過 |
空白節(jié)點 | 通過 | 通過 | 通過 | 通過 | 通過 |
字符’”/\ | 通過 | 通過 | \ ‘’未通過 | 通過 | 通過 |
多層嵌套 | 通過 | 通過 | 通過 | 通過 | 通過 |
語法檢測 | 通過 | 通過 | 不能通過,在if else語句中常用的形態(tài)不能處理。 | 通過 | 通過 |
?流程??
對于“什么是前端模板,它有什么特性,怎么使用”這樣的問題已經(jīng)通過上面的分析說明給出了答案。但前端模板既然是前端的范疇,就不可能獨立存在,而是需要運用到前端開發(fā)的流程中的。而采用了前端模版的開發(fā)流程與傳統(tǒng)的相比又會是怎么樣的呢?
?
上圖是傳統(tǒng)的開發(fā)流程。首先將ui設(shè)計圖轉(zhuǎn)換成html的頁面,其中的數(shù)據(jù)一般先用模擬數(shù)據(jù)代替。比如,ui設(shè)計有個列表,那么可能開發(fā)人員會先建立一些模擬的數(shù)據(jù)填充到節(jié)點中,來開發(fā)調(diào)整頁面樣式。最后一步,則將需要動態(tài)生成(ajax應(yīng)用等)的地方,將模擬數(shù)據(jù)的節(jié)點變成空白節(jié)點,然后在javascript里面拼裝這些html節(jié)點的字符串,最后再還原到原節(jié)點處(比如用innerHTML插入html)。
?
上圖是一個實例。當列表中的元素需要ajax動態(tài)加載的時候,在傳統(tǒng)開發(fā)中可能按照先開發(fā)模擬數(shù)據(jù)的html頁面,再將這些元素拼接成html字符串,之后再進行一系列處理的功能。
那么,它的問題是什么呢?很明顯,“不可逆”是最大的問題。當開發(fā)者完成了開發(fā),這時候如果需要修改,那么將是很頭疼的事。由于是由字符串拼接出來的html片段,想直接修改這些字符串來改變結(jié)構(gòu)或是修改樣式什么的將是一個比重新開發(fā)一遍還要具有挑戰(zhàn)的工作。所以,開發(fā)者往往選擇再來一遍吧:html的模擬數(shù)據(jù)頁面,然后再拼接字符串。除了“不可逆”,維護性差以及開發(fā)成本高都是采用傳統(tǒng)方式開發(fā)富客戶端應(yīng)用的弊病。
好吧,我們試著改變這個局面??纯聪聢D,采用前端模板開發(fā)的新方式,或許會找到某些答案。
?
?
?
“雙向可逆”,是的,采用前端模板的開發(fā)方式,在開發(fā)好展示的html頁面后,直接經(jīng)過簡單的修改即可生成html+template 頁面,無需再拼接字符串,無需再反復重寫展示模擬數(shù)據(jù)的html頁面,一切都變得很輕松。我們來看看代碼便知道原因了(以ace template為例)。
?如果調(diào)用模板引擎,當模板執(zhí)行數(shù)據(jù)執(zhí)行后,直接覆蓋parentNode里面的內(nèi)容。而如果想繼續(xù)調(diào)整html結(jié)構(gòu)等,則不調(diào)用模板引擎即可。而原有的調(diào)試數(shù)據(jù),在需要發(fā)布的時候可以直接通過代碼編譯去掉debug start與debug end之間代碼即可(這僅僅是前端模塊開發(fā)的一種實例,實際開發(fā)中可以去掉模擬數(shù)據(jù),不用編譯)。
前端模板技術(shù)其實還有很多的工作要做,比如模板的事件代理,模板的復用性,模板的組件庫等等。本文僅對前端模板做了一個大致講解。相信隨著對于前端模板的探索,模板技術(shù)會被越來越多得運用的前端開發(fā),特別是富客戶端的前端開發(fā)中,進一步提高開發(fā)效率,為開發(fā)人員帶來更多的驚喜!