溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

初識前端模板

發(fā)布時間:2020-08-03 09:30:37 來源:網(wǎng)絡 閱讀:537 作者:可樂程序員 欄目:web開發(fā)

總述?

“模板”這個詞,可能很多人第一印象是后端的技術(Smarty,Velocity等),但本文要講的卻不是后端的概念,而是前端開發(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中寫<ul><li><%= name %></li></ul>的時候,其實就是在應用模板,在后臺這句話會被轉換成out.print(“<ul><li>”+name+”</li></ul>”)。模板的數(shù)據(jù)渲染就是把模板中的占位符(這里是”name”),替換成傳入的值(比如替換成”yaya”)。而在前端開發(fā)中,這種方式依然具有很高實用價值。前端模板的核心是前端模板引擎,引擎將前端的模板語言轉換成瀏覽器可以解析的html語言。當轉換成功后,便可以很方便地將這段html代碼放到我們希望的地方去。

?

初識前端模板

比如我們可以寫一段循環(huán)的li標簽的前端模板語言。通過前端模板引擎轉換后成本一連串得li標簽的html語言。這時候就可以直接采用innerHTML方法把html代碼插入到ul對象中,那么就完成了生成ul列表的功能。

?初識??

前端的模板核心是模板解析引擎,而解析引擎的主要作用是將模板語言轉換成html/xml格式。不同的前端模板有著不同的模板語言,解析引擎因此也各不相同。讓我們先來認識幾款前端模板,了解下它們各自的模板語言。

Yaya Template是一款輕量級的模板引擎,采用原生javascript語法,具有易學易用等特點。我們來看一段用Yaya Template渲染列表數(shù)據(jù)的實例:

模板語言(通用過for循環(huán),輸出“這是第n列”的li列表)

?


for(var i=0;i<list.length;i++){

{$ <li>這是第?{% i %}?列:{% list[i] %}</li> $}

}


??

有了模板語言后,我們只需要將數(shù)據(jù)“打入”模板語言中的”list”,就可以生成我們想要的html/xml格式了。如上例,我們只需要得到這個模板語言進行翻譯,并調用對應的render方法,

?


var list = [“紅桃”,”方塊”,”梅花”,”黑桃”];

var html = YayaTemplate(templateText).render({list:list});


??

這個html則是模板引擎轉換成的html/xml語言,在上例中,則為:

?


<li>這是第0列:紅桃</li>

<li>這是第1列:方塊</li>

<li>這是第2列:梅花</li>

<li>這是第3列:黑桃</li>


?

從這個例子中,我們可以發(fā)現(xiàn),{$…$}表示輸出的html/xml片段,{%…%}表示輸出javascript變量。得到的html,我們可以用直接作為dom的innerHTML或者其他用處。

這便是前端模板,它使得我們不必去處理字符串拼接等問題,用最直觀的方式來渲染數(shù)據(jù)。我們再來看另外一款前端模板EasyTemplate。還是之前的例子,用EasyTemplate模板寫法如下:

?


<#list data as list>

<li>這里是第${list_index}?列:${list}</li>

</#list>


??

同樣,需要將實際數(shù)據(jù)替換模板變量,這里采用:


var list = [“紅桃”,”方塊”,”梅花”,”黑桃”];

var html = easyTemplate.render(templateText,list); //templateText指模板語言


?像EasyTemplate這樣的前端模板,是屬于自定義模板語言的一種前端模板。我們可以從上例看出,””就是EasyTemplate自定義的循環(huán)條件。像這樣EasyTemplate?模板一樣采用自定義標簽的前端模板還有?lite Template:


<c:for var=”item” list=”${list}”>

<li>這里是第${for.index}列:${item}</li>

</c:for>


?

渲染時采用:


var list = [“紅桃”,”方塊”,”梅花”,”黑桃”];

var html = liteFunction(templateText,’list’)(list);


?

好了,我們再來看看jquery作者John Resig所寫的一個前端模板jquery template。說真的,它如同jquery一樣,短小精悍。還是老例子:


<% for(var i=0;i<list.length;i++){ %>

<li>這是第?<%=i%>?列:<%= list[i] %></li>

<% } %>


??

渲染采用:


var list = [“紅桃”,”方塊”,”梅花”,”黑桃”];

var html = tmpl(“templateid”, list);


??我們可以看出,Yaya Templatejquery template在模板語言的寫法上正好相反。前者將輸出html語言做特殊標記{$…$},而后者對javascript語言做特殊標記。這兩種模板已經(jīng)使得學習成本很低了,而接下來介紹的ace template的寫法將更加簡單易懂。


for(var i=0;i<list.length;i++){

<li>這是第?#{ i }?列:#{ list[i] }</li>

}


??

渲染采用:


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),這包括寫法與用法等直觀印象。但我們知道,前端模板的核心是代碼的轉換,這肯定是需要轉換時間的,那就以上五個不同的前端模板,性能上會有怎樣不同的表現(xiàn)呢。??

性能??

前端模板語言到html/xml語言,是通過模板引擎進行翻譯的。而模板引擎的翻譯性能在某種程度上決定了前端模板解決方案的可行性的高低。上訴五種前端模板,各自的性能會是怎么樣的,我們對它們進行測試。分別對Yaya Template、EasyTemplate、jquery template、?ace template、lite template部署前端模板做同樣的操作,比較模板引擎翻譯時間代價。

各自的模板代碼如下:

Yaya Templat?


for (var i=0;i<list.length;i++){

if (i<100){

{$<li>小于100?這里是第{%i%}?列:{%list[i]%}</li>$}

}

else{

{$<li>不小于100?這里是第{%i%}?列:{%list[i]%}</li>$}

}

}


??

EasyTemplate?


<#list data as list>

<#if (list_index <100)>

<li>小于100?這里是第${list_index}?列:${list}</li>

<#else>

<li>不小于100?這里是第${list_index}?列:${list}</li>

</#if>

</#list>


??

jquery template?


<% for (var i=0;i<list.length;i++){ %>

<% if (i<100) { %>

<li>小于100?這里是第<%=i%>列:<%=list[i]%></li>

<% } else{ %>

<li>不小于100?這里是第<%=i%>列:<%=list[i]%></li>

<% } %>

<% } %>


?

ace template?


for (var i=0;i<list.length;i++){

if (i<100){

<li>小于100?這里是第#{i}?列:#{list[i]}</li>

}

else{

<li>不小于100?這里是第#{i}?列:#{list[i]}</li>

}

}


?

lite template?


<c:for var=”item” list=”${list}”>

<c:if test=”${for.index&lt;100}”>

<li>?100?這里是第?$!{for.index}?列:$!{item}</li>

</c:if>

<c:else>

<li>不小于100?這里是第$!{for.index}?列:$!{item}</li>

</c:else>

</c:for>


??

然后我們改變list數(shù)組里面的元素個數(shù),對各個模板翻譯執(zhí)行的時間進行記錄。結果如下(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


?

通過第一次翻譯后,如果前端模板可以緩存翻譯后的中間代碼,或者可以返回構建中間代碼的函數(shù),那么再次渲染數(shù)據(jù)的時候,就不需要再翻譯。這樣可以極大的縮小渲染數(shù)據(jù)的時間,提高速度。

綜合各種調研數(shù)據(jù)對比表如下:?



Yaya Template

EasyTemplate

jquery template

ace template

lite template

緩存加速

防xss漏洞編碼

擴展語法

錯誤跟蹤

代碼尺寸(字節(jié))

483

1527

453

2512

91511


?兼容

?前端模板的兼容性也是一個重要的問題。能夠實現(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設計圖轉換成html的頁面,其中的數(shù)據(jù)一般先用模擬數(shù)據(jù)代替。比如,ui設計有個列表,那么可能開發(fā)人員會先建立一些模擬的數(shù)據(jù)填充到節(jié)點中,來開發(fā)調整頁面樣式。最后一步,則將需要動態(tài)生成(ajax應用等)的地方,將模擬數(shù)據(jù)的節(jié)點變成空白節(jié)點,然后在javascript里面拼裝這些html節(jié)點的字符串,最后再還原到原節(jié)點處(比如用innerHTML插入html)。

?

初識前端模板

上圖是一個實例。當列表中的元素需要ajax動態(tài)加載的時候,在傳統(tǒng)開發(fā)中可能按照先開發(fā)模擬數(shù)據(jù)的html頁面,再將這些元素拼接成html字符串,之后再進行一系列處理的功能。

那么,它的問題是什么呢?很明顯,“不可逆”是最大的問題。當開發(fā)者完成了開發(fā),這時候如果需要修改,那么將是很頭疼的事。由于是由字符串拼接出來的html片段,想直接修改這些字符串來改變結構或是修改樣式什么的將是一個比重新開發(fā)一遍還要具有挑戰(zhàn)的工作。所以,開發(fā)者往往選擇再來一遍吧:html的模擬數(shù)據(jù)頁面,然后再拼接字符串。除了“不可逆”,維護性差以及開發(fā)成本高都是采用傳統(tǒng)方式開發(fā)富客戶端應用的弊病。

好吧,我們試著改變這個局面??纯聪聢D,采用前端模板開發(fā)的新方式,或許會找到某些答案。

?

初識前端模板

?

?

“雙向可逆”,是的,采用前端模板的開發(fā)方式,在開發(fā)好展示的html頁面后,直接經(jīng)過簡單的修改即可生成html+template 頁面,無需再拼接字符串,無需再反復重寫展示模擬數(shù)據(jù)的html頁面,一切都變得很輕松。我們來看看代碼便知道原因了(以ace template為例)。

初識前端模板

?如果調用模板引擎,當模板執(zhí)行數(shù)據(jù)執(zhí)行后,直接覆蓋parentNode里面的內容。而如果想繼續(xù)調整html結構等,則不調用模板引擎即可。而原有的調試數(shù)據(jù),在需要發(fā)布的時候可以直接通過代碼編譯去掉debug start與debug end之間代碼即可(這僅僅是前端模塊開發(fā)的一種實例,實際開發(fā)中可以去掉模擬數(shù)據(jù),不用編譯)。

展望??

前端模板技術其實還有很多的工作要做,比如模板的事件代理,模板的復用性,模板的組件庫等等。本文僅對前端模板做了一個大致講解。相信隨著對于前端模板的探索,模板技術會被越來越多得運用的前端開發(fā),特別是富客戶端的前端開發(fā)中,進一步提高開發(fā)效率,為開發(fā)人員帶來更多的驚喜!

向AI問一下細節(jié)
推薦閱讀:
  1. 初識UNIX
  2. puppet 初識

免責聲明:本站發(fā)布的內容(圖片、視頻和文字)以原創(chuàng)、轉載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權內容。

AI