掌握js模板引擎


最近要做一個小項目,不管是使用angularjs還是reactjs,都覺得大材小用了。其實我可能只需要引入一個jquery,但想到jquery對dom的操作,對於早已習慣了雙向綁定模式的我,何嘗不是一種痛苦。

聽過這樣一句話:“技術沒有缺席,只有姍姍來遲”,很多技術自己不知道,並非沒有。今天我想介紹的就是一個簡單的js模板引擎artTemplate,讓我們揚帆起航吧~

一、概述

artTemplate 是新一代 javascript 模板引擎,它采用預編譯方式讓性能有了質的飛躍,並且充分利用 javascript 引擎特性,使得其性能無論在前端還是后端都有極其出色的表現。

二、我的痛點

我們先來看一段代碼,當我用ajax從后台拿到一堆json數據,要填充進頁面的時候,可能會這么做:

1
2
3
4
5
6
7
8
9
10
11
12
$.ajax({
type: 'GET',
url: '/server/list.json',
success: function(data) {
var lists = '';
for(var i=0;i<data.content.rows.length;i++){
lists += '<li><div class="lititle">'+data.content.rows[i].leaveRuleName+'(共計 '+data.content.rows[i].durationStr+')</div><div class="timer"><span>開始時間:'+data.content.rows[i].startTime+'</span><span>結束時間:'+data.content.rows[i].endTime+'</span></div><div class="btns"><p><a href="#" class="button button-round blue">'+data.content.rows[i].customApprovalStatus+'</a></p></div><div class="info">剛剛申請</div></li>';
}
$('#myList').append(lists);
},
error: function(xhr, type) {
})

html代碼:

1
<ul class="list-container" id="myList"></ul>

這段代碼,功能上可能並沒有什么問題。但是我們來看lists變量,這里面的信息已經爆炸了,html結構以及data填充,寫完我就不想維護了。

正應了那句話:“此時我寫的代碼,只有我和天知道。半個月后,恐怕只有天知道了!”

三、處理痛點

這豈止是一場噩夢,簡直就是在挖坑埋雷🙈。好了,不再矯情了,我們換artTemplate來試試,代碼可能是這樣:


1
2
3
4
5
6
7
8
$.ajax({
type: 'GET',
url: '/server/list.json',
success: function(data) {
$('#myList').append(template('myListTpl', { lists: data.content.rows}));
},
error: function(xhr, type) {
})

html代碼:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<script type="text/html" id="myListTpl">
{{each lists}}
<li data-id="{{$value.id}}">
<div class="lititle">{{$value.overtimeRuleName}}(共計 {{$value.durationStr}})</div>
<div class="timer">
<span>開始時間:{{$value.startTime}}</span>
<span>結束時間:{{$value.endTime}}</span>
</div>
<div class="btns">
<p><a href="#" class="button button-round {{!$value.isEnsure?'blue':($value.isEffective?'green':'red')}}">{{!$value.isEnsure?'待確認':($value.isEffective?'已確認':'已失效')}}</a></p>
</div>
<div class="info">{{$value.applyTime | timeFormat}}申請</div>
</li>
{{/each}}
</script>
<ul class="list-container" id="myList"></ul>

注意:script中的type=”text/html”

這段代碼很清晰,我們建立了myListTpl作為模板,里面的html結構清晰,變量包在了雙大括號中。那么lists中的值是怎么來的,細心的你可能看到了這個:

1
$('#myList').append(template('myListTpl', { lists: data.content.rows}));

對,我們用template去預編譯模板,同時將數據塞進了lists中。就這樣,js中不需要很復雜的邏輯,html也保存了原有的結構。

~嗡~嗡,嗯,整個世界都清靜了!

四、用法示例

artTemplate用起來很簡單,我們來逐一舉例說明:

1.template(id,data),向id模板傳入數據。

1
2
3
4
5
6
7
8
<script id="test" type="text/html">
<h1>{{title}}</h1>
<ul>
{{each list as value i}}
<li>索引 {{i + 1}} :{{value}}</li>
{{/each}}
</ul>
</script>

js代碼:

1
2
3
4
5
6
var data = {
title: '標簽',
list: ['文藝', '博客', '攝影', '電影', '民謠', '旅行', '吉他']
};
var html = template('test', data);
document.getElementById('content').innerHTML = html;

2.template.compile(source,options),預編譯模板數據。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<script>
var source = '<ul>'
+ '{{each list as value i}}'
+ '<li>索引 {{i + 1}} :{{value}}</li>'
+ '{{/each}}'
+ '</ul>';

var render = template.compile(source);
var html = render({
list: ['攝影', '電影', '民謠', '旅行', '吉他']
});

document.getElementById('content').innerHTML = html;
</script>

上面兩種方式,屬於簡單的數據渲染,實際應用中我們可能會碰到比較復雜的操作,下面細說。

3.template.helper(name,callback),在模板中使用自定義方法。
某種情況下,我們需要對數據做一下預處理,類似angularjs中的filter操作,那怎么辦呢?

1
2
3
<script id="test" type="text/html">
大專欄  掌握js模板引擎 class="undefined">{{time | timeFormat}}
</script>

1
2
3
4
template.helper('timeFormat',function(date){
var result = Common.formateTime(date);
return result;
});

如上所示,我們調用了template.helper方法,將自定義方法放在回調函數中,那么數據是不是可以進行處理了呢。這里我的場景是對時間數據做了格式化處理,我希望他顯示成“1小時前,剛剛”之類的文案。

4.template.config(name,value),更改引擎的默認配置。
配置

5.include可嵌套子模板。

1
2
3
4
5
6
7
8
9
10
11
12
<div id="content"></div>
<script id="test" type="text/html">
<h1>{{title}}</h1>
{{include 'list'}}
</script>
<script id="list" type="text/html">
<ul>
{{each list as value i}}
<li>索引 {{i + 1}} :{{value}}</li>
{{/each}}
</ul>
</script>

js代碼:

1
2
3
4
5
6
var data = {
title: '嵌入子模板',
list: ['文藝', '博客', '攝影', '電影', '民謠', '旅行', '吉他']
};
var html = template('test', data);
document.getElementById('content').innerHTML = html;

重點在於:

1
{{include 'list'}}

將id為list的模板包含進來,很簡單,這里就不細說了。

6.轉義

1
2
3
4
5
<div id="content"></div>
<script id="test" type="text/html">
<p>不轉義:{{#value}}</p>
<p>默認轉義: {{value}}</p>
</script>

js代碼:

1
2
3
4
5
var data = {
value: '<span style="color:#F00">hello world!</span>'
};
var html = template('test', data);
document.getElementById('content').innerHTML = html;

我們只需要加上“#”號,模板默認就不轉義啦。

7.在頁面上打印你的數據。
當然,你還可以這么玩:

1
2
3
<script id="test" type="text/html">
{{print a b c}}
</script>

js代碼:

1
2
3
4
5
6
7
8
var html = '';
var data = {
a: 'hello',
b: '--world',
c: '--!!!'
};
html = template('test', data);
document.write(html);

基本用法就這些了,是不是覺得很簡單呢,那就趕快試試吧!

五、原理剖析

當然,我們並不會只停留在會用的層次上面,模板引擎又是如何工作的呢?

artTemplate 模板編譯器會根據一些簡單的規則提取好所有模板變量,聲明在渲染函數頭部,這個函數類似:

1
2
3
4
5
6
7
8
9
10
var render = function($data){
var content = $data.content,
$out = '';
$out += '<h3>';
if(typeof content === 'string'){
$out += content;
}
$out += '</h3>';
return $out;
};

這個自動生成的函數就如同一個手工編寫的 javascript 函數一樣,同等的執行次數下無論 CPU 還是內存占用都有顯著減少,性能近乎極限。

值得一提的是:artTemplate 很多特性都基於預編譯實現,如沙箱規范與自定義語法等。

雖然每個引擎從模板語法、語法解析、變量賦值、字符串拼接的實現方式各有所不同,但關鍵的渲染原理仍然是動態執行 javascript 字符串。

嗯,點到為止吧。如果想深入了解,去下載個template.js,看看源碼吧。

六、負荷測試與調試

負荷測試
在 chrome 下渲染效率測試中分別是知名引擎 Mustache 與 micro tmpl 的 25 、 32 倍。
除了性能優勢外,調試功能也值得一提。模板調試器可以精確定位到引發渲染錯誤的模板語句,解決了編寫模板過程中無法調試的痛苦,讓開發變得高效,也避免了因為單個模板出錯導致整個應用崩潰的情況發生。示例如下:

1
2
3
4
5
6
7
8
<script id="test" type="text/html">
<ul>
{{each list}}
{{/each}}

{{window.alert=null}}
</ul>
</script>

js代碼:

1
2
3
var html = '';
html = template('test', {});
document.write(html);

list變量並沒有賦值,模板引擎會將錯誤拋出,方便定位與查錯。

七、意外收獲

原本我以為artTemplate會是最快的,結果又發現了doT,很好,你已經成功引起了我的注意。
doT
正如大家所見,js模板引擎五花八門,如果每個引擎寫一篇文章,我想幾年內我應該不用干其他事了(我才不會這么無聊呢👻)。so,不要糾結到底使用哪個模板引擎。請記住,適合自己的才是最好的。

八、總結

按照學習思路,從上到下有了這篇文章。之所以想要詳細的去寫一篇關於模板引擎的文章,主要是想彌補心里的內疚。其實早在2014年我就有聽說過artTemplate,但卻只止步於聽過的程度。

當地球人都在用的時候,我還沒有開始,當大家已經去追逐天邊的雲彩,我才反應過來。

血淋淋的教訓,謹以此獻給和我有同樣遭遇以及感受的人們,任何時間請不要停下學習的腳步,哪怕晚了,但至少你努力過。

九、參考文章

1.官方文檔:
https://github.com/aui/artTemplate
2.快速上手:
https://github.com/aui/artTemplate
3.原理解析:
http://cdc.tencent.com/2012/06/15/高性能javascript模板引擎原理解析/
4.官方示例:
https://github.com/aui/artTemplate/tree/master/demo


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM