jsrender官網(wǎng)號(hào)稱簡(jiǎn)單直觀谊惭、強(qiáng)大輕快可擴(kuò)展鳄梅。壓縮體積也只有8.9kb,可以單獨(dú)在瀏覽器或node中使用驶忌,也可以配合jQuery使用。
jsrender使用 {{}} 來(lái)做分界笑跛,如果{{}}與你現(xiàn)有的模板引擎沖突你可以使用api來(lái)自定義付魔,比如:
$.views.settings.delimiters("<%", "%>");
//原本
<p>{{:name}}</p>
//修改后
<p><%:name%></p>
一聊品、基本語(yǔ)法
1. 基本變量標(biāo)簽 {{:name}}
基本變量需要使用冒號(hào) ":" 作為標(biāo)識(shí),一般是簡(jiǎn)單對(duì)象的某個(gè)屬性几苍。比如傳入一個(gè)簡(jiǎn)單對(duì)象data
//模板
<script type="text/x-jsrender" id="j-specCard">
<table>
<tr>
<td>Name: {{:name}}</td>
<td>Age: {{:age}}</td>
</tr>
</table>
</script>
//邏輯
(function(jq, g) {
//傳入一個(gè)簡(jiǎn)單對(duì)象
var data = {
'name': 'alice',
'age': 18
},
//獲取模板
jsRenderTpl = $.templates('#j-specCard'),
//末班與數(shù)據(jù)結(jié)合
finalTpl = jsRenderTpl(data);
$('.box').html(finalTpl);
})(jQuery, window);
//傳入一個(gè)多層級(jí)對(duì)象complexData
<body>
<div class="box"></div>
<script type="text/x-jsrender" id="j-specCard">
<table>
<tr>
<td>Name: {{:personalInfo.name}}</td>
<td>Age: {{:personalInfo.age}}</td>
</tr>
</table>
<p>{{:top.middle1}}</p>
<p>{{:top.middle.bottom}}</p>
</script>
</body>
<script src="../lib/jquery-1.11.2.min.js"></script>
<script src="../lib/jsrender.js"></script>
<script>
(function(jq, g) {
var complexData = {
'personalInfo': {
'name': 'alice',
'age': 18
},
'top': {
'middle': {
'bottom': 'this is bottom value'
},
'middle1': 'this is middle1 value'
}
},
//獲取模板
jsRenderTpl = $.templates('#j-specCard'),
//末班與數(shù)據(jù)結(jié)合
finalTpl = jsRenderTpl(complexData);
$('.box').html(finalTpl);
})(jQuery, window)
</script>
如上所見翻屈,不管傳入的對(duì)象有多復(fù)雜,都能按照層級(jí)去到屬性妻坝,只是把最外層的對(duì)象名省略掉了伸眶。
2. 對(duì)基本變量有轉(zhuǎn)譯功能標(biāo)簽{{>name}}
轉(zhuǎn)譯功能標(biāo)簽使用大于號(hào) ">" 作為標(biāo)識(shí),可以讓數(shù)據(jù)原樣輸出惠勒,可以防止注入攻擊赚抡。比如
<body>
<div class="box"></div>
<script type="text/x-jsrender" id="j-specCard">
<p>{{:name}}</p>
<p>{{>name}}</p>
</script>
</body>
<script src="../lib/jquery-1.11.2.min.js"></script>
<script src="../lib/jsrender.js"></script>
<script>
(function(jq, g) {
var data = {
'name': '<b style="font-size:24px;">i am alice</b><script>alert("我是注入腳本攻擊")<\/script>'
},
//獲取模板
jsRenderTpl = $.templates('#j-specCard'),
//末班與數(shù)據(jù)結(jié)合
finalTpl = jsRenderTpl(data);
$('.box').html(finalTpl);
})(jQuery, window)
</script>
雖然{{>}}有轉(zhuǎn)譯功能爬坑,我們不一定必須用他纠屋,因?yàn)橛行?biāo)簽我們還是需要顯示的,視具體情況而定
3. 啟用與定義全局變量的標(biāo)簽{{*}}與 {{*:}},不支持代碼語(yǔ)法盾计,如果是代碼售担,那么會(huì)咦字符串的形式輸出
在jsrender語(yǔ)法中,不僅可以處理簡(jiǎn)單的對(duì)象署辉,也支持表達(dá)式族铆,比如
<p>{{*:name.firstName + ' ' + name.lastName </p>
var data = {
'name': {
'firstName': 'cury',
'lastName': 'steven'
}
}
但是為了保證封裝性,并不是任何表達(dá)式都可以處理的哭尝,比如全局變量window就不行哥攘。比如
<p>{{:name.firstName + ' ' + name.lastName + ' ' + window.describe}}</p>
window.describe = " he is a basketball player";
這樣的代碼會(huì)報(bào)錯(cuò)的 Uncaught TypeError: Cannot read property 'describe' of undefined。即使這樣材鹦,jsrender給我提供了手動(dòng)開啟的方式逝淹,只需要調(diào)用api,并且使用{{*:}}標(biāo)簽就可以使用了桶唐。比如
<body>
<div class="box"></div>
<script type="text/x-jsrender" id="j-specCard">
<!--除了可以在js中定義全局變量栅葡,在模板中也是可以的-->
{{* window.count = 1}}
<p>{{*:count + 2}}</p>
<p>{{:name.firstName + ' ' + name.lastName + ' ' + window.describe}}</p>
<!-- <p>{{*:describe + ' ' + name + count}}</p> -->
</script>
</body>
<script src="../lib/jquery-1.11.2.min.js"></script>
<script src="../lib/jsrender.js"></script>
<script>
(function(jq, g) {
window.describe = " he is a basketball player";
$.views.settings.allowCode(true);
var data = {
'name': {
'firstName': 'cury',
'lastName': 'steven'
}
},
//獲取模板
jsRenderTpl = $.templates('#j-specCard'),
//末班與數(shù)據(jù)結(jié)合
finalTpl = jsRenderTpl(data);
$('.box').html(finalTpl);
})(jQuery, window)
</script>
首先需要執(zhí)行$.views.settings.allowCode(true);,把設(shè)置開啟尤泽,然后使用{{* window.count = 1}}定義一個(gè)變量欣簇,然后再用{{*:count}}引用變量。當(dāng)然坯约,jsrender也提供了只有某一個(gè)模板支持全局變量的設(shè)置方式
var tmpl = $.templates({
markup: "#myTemplate",
allowCode: true
});
4. 注釋的標(biāo)簽 {{!-- --}}
在jsrender模板中熊咽,html的注釋是不起作用的,jsrender會(huì)原樣的輸出到dom節(jié)點(diǎn)中闹丐,而dom中是認(rèn)識(shí)這個(gè)注釋的横殴,所以并不會(huì)顯示。但是呢妇智,如果注釋中有未定義的變量滥玷,那么jsrender就會(huì)報(bào)錯(cuò)氏身,比如
<script type="text/x-jsrender" id="j-specCard">
<p>這是jsrender模板</p>
<!-- <p>{{*:describe + ' ' + name + count}}</p> -->
</script>
如果我沒(méi)有定義window.describe 跟window.count變量,那么這段代碼就會(huì)報(bào)錯(cuò)惑畴,所以我們?cè)趈srender模板中要使用jsrender的注釋{{!-- --}},而且jsrender在渲染的時(shí)候是不會(huì)把注釋代碼返回的蛋欣。
5. 條件判斷語(yǔ)句 {{if}} {{else}}
jsrender 的if else 語(yǔ)法跟正常的代碼邏輯還是有點(diǎn)區(qū)別的,當(dāng)只有兩種情況的時(shí)候如贷,是沒(méi)有區(qū)別的陷虎,就是if else
<script type="text/x-jsrender" id="j-specCard">
{{if name == 'alice'}}
<p>Hello Alice</p>
{{else}}
<p>Hello tourisor</p>
{{/if}}
</script>
但是當(dāng)有多種情況的時(shí)候,也就是if elseif elseif else的時(shí)候杠袱,可是jsrender并沒(méi)有elseif這樣的寫法尚猿,它會(huì)根據(jù)情況來(lái)判斷,如果是多重情況楣富,它會(huì)自動(dòng)把else 當(dāng)做elseif來(lái)使用
<script type="text/x-jsrender" id="j-specCard">
{{if count == 1}}
<p>welcome first!</p>
{{else count == 2}}
<p>welcome again</p>
<p>這里的else會(huì)被當(dāng)做elseif count==2 使用</p>
{{else}}
<p>welcom back!</p>
{{/if}}
</script>
if else 除了以{{if}}....{{/if}}block閉合的形式使用凿掂,也可以使用{{if xxx=true ... /}}自閉合的形式,而且還可以引入模板
<script type="text/x-jsrender" id="j-specCard">
{{if count == 1 tmpl="#j-firstTpl" /}}
</script>
<script type="text/x-jsrender" id="j-firstTpl">
<h3>this is first template</h3>
</script>
當(dāng)然如果你的情況比較復(fù)雜,那么你可以混著用
<script type="text/x-jsrender" id="j-specCard">
{{if count == 1 tmpl="#j-firstTpl" }}
{{else count == 2 tmpl="#j-secondTpl"}}
{{else}}
<p>no template</p>
{{/if}}
</script>
<script type="text/x-jsrender" id="j-firstTpl">
<h3>this is first template</h3>
</script>
<script type="text/x-jsrender" id="j-secondTpl">
<h3>this is second template</h3>
</script>
有了引用模板的功能纹蝴,我們就完全可以把比較通用的代碼提取出來(lái)寫一個(gè)模板庄萎,減少代碼的冗余。
6. 使用{{for}}循環(huán)對(duì)數(shù)據(jù)進(jìn)行循環(huán)或?qū)?duì)象進(jìn)行遍歷
jsrender的for循環(huán)會(huì)默認(rèn)把數(shù)組或?qū)ο蟮牡谝粚友h(huán)遍歷掉塘安,我們只要管里面的數(shù)據(jù)就行了糠涛,而且使用了循環(huán)之后的模板也可以單獨(dú)寫成一個(gè)模板,在for循環(huán)中引用,循環(huán)數(shù)組的時(shí)候可以使用{{:#index}}來(lái)獲取當(dāng)前數(shù)組的下標(biāo)兼犯,并且index是從0開始忍捡。
傳入模板的數(shù)據(jù)結(jié)構(gòu)
<script>
(function(jq, g) {
var animal = {
'kind': 4,
'price':{
'cow': 19999,
'pig': 1888
},
'list': [
{
'name': 'cow',
'count': 4,
'foot': 4
},
{
'name': 'chicken',
'count': 5,
'foot': 2
}
]
},
//獲取模板
jsRenderTpl = $.templates('#j-specCard'),
//末班與數(shù)據(jù)結(jié)合
finalTpl = jsRenderTpl(animal);
$('.box').html(finalTpl);
})(jQuery, window)
</script>
<script type="text/x-jsrender" id="j-specCard">
{{!-- animal 對(duì)象已經(jīng)被默認(rèn)遍歷,所以屬性前不用加animal.就可訪問(wèn)到 --}}
<h3>there have {{:kind}} kinds animal</h3>
<p>and the cow price is {{:price.cow}}</p>
<p>and the cow price is {{:price.pig}}</p>
{{!--
也可以這樣對(duì)對(duì)象進(jìn)行for循環(huán)
{{for price}}
<p>and the cow price is {{:cow}}</p>
<p>and the cow price is {{:pig}}</p>
{{/for}}
--}}
<ul>
{{!-- 對(duì)對(duì)象數(shù)組進(jìn)行循環(huán) --}}
{{for list}}
<li>{{:#index + 1}}. this animal call {{:name}}, and has {{:count}}, it has {{:foot}} foots</li>
{{/for}}
{{!--
也可以使用模板引入作為循環(huán)的模板
{{for list tmpl="#j-listTpl" /}}
--}}
</ul>
</script>
<script type="text/x-jsrender" id="j-listTpl">
<li>this animal call {{:name}}, and has {{:count}}, it has {{:foot}} foots</li>
</script>
當(dāng)循環(huán)數(shù)組或者遍歷對(duì)象的時(shí)候切黔,如果在{{for}}{{/for}}中間加上{{else}}砸脊,還可以對(duì)遍歷的對(duì)象進(jìn)行判斷,如果該對(duì)象或者屬性不存在绕娘,那么就顯示其他的內(nèi)容脓规。
{{!-- 遍歷的時(shí)候順便判斷merbers是否存在 --}}
{{for members}}
<div>{{:name}}</div>
{{else}}
<div>No members!</div>
{{/for}}
7. 使用{{props}}遍歷對(duì)象并且獲取到對(duì)象的key/value
當(dāng)我們遍歷對(duì)象需要使用到對(duì)象的key值時(shí),使用props可以獲取到key/value值险领,而且也可以在for循環(huán)中進(jìn)行對(duì)象的遍歷,在數(shù)據(jù)循環(huán)中獲取可以使用#data獲取到當(dāng)前的對(duì)象侨舆,當(dāng)然也可以使用引入外部模板來(lái)當(dāng)做循環(huán)模板。
傳入模板的數(shù)據(jù)結(jié)構(gòu)
<script>
(function(jq, g) {
var animal = {
'kind': 4,
'price':{
'cow': 19999,
'pig': 1888
},
'list': [
{
'name': 'cow',
'count': 4,
'foot': 4
},
{
'name': 'chicken',
'count': 5,
'foot': 2
}
]
},
//獲取模板
jsRenderTpl = $.templates('#j-specCard'),
//末班與數(shù)據(jù)結(jié)合
finalTpl = jsRenderTpl(animal);
$('.box').html(finalTpl);
})(jQuery, window)
</script>
模板
<script type="text/x-jsrender" id="j-specCard">
{{!-- 簡(jiǎn)單的對(duì)象遍歷 --}}
{{props price}}
<p>and the {{:key}} price is {{:prop}}</p>
{{/props}}
<ul>
{{!-- 在數(shù)據(jù)循環(huán)中再進(jìn)行對(duì)象的遍歷绢陌,病獲取到key/prop --}}
{{for list}}
<li>{{:#index + 1}}.
{{props #data}}
<b>{{:key}}</b> is {{>prop}}
{{/props}}
</li>
{{/for}}
{{!--
也可以使用模板引入作為循環(huán)的模板
{{for list tmpl="#j-listTpl" /}}
--}}
</ul>
</script>
<script type="text/x-jsrender" id="j-listTpl">
<li>{{:#index + 1}}.
{{props #data}}
<b>{{:key}}</b> is {{>prop}}
{{/props}}
</li>
</script>
當(dāng)然挨下,在prop也可以在遍歷對(duì)象的時(shí)候?qū)?duì)象進(jìn)行判斷,只要在prop變遷中加入{{else}}脐湾,如果對(duì)象為undefined或?qū)ο鬄榭粘舭剩敲淳蛨?zhí)行else邏輯。
{{props address}}
<b>{{>key}}:</b>{{>prop}} <br />
{{else}}
The address is blank (no properties)!
{{/props}}
8. 使用{{include}}引入外部模板或者改變模板的上下文
雖然我們可以在{{for}}循環(huán)中或者{{if}}標(biāo)簽中直接引入模板,但是{{include}}引入模板才是符合我們的認(rèn)知愁铺,應(yīng)該什么標(biāo)簽該干什么事來(lái)的鹰霍。
<script type="text/x-jsrender" id="j-specCard">
{{if case == 1}}
{{include tmpl="#j-case1Tpl" /}}
{{else case == 2}}
{{include tmpl="#j-case2Tpl" /}}
{{else}}
<p>no data</p>
{{/if}}
</script>
<script type="text/x-jsrender" id="j-case1Tpl">
<h3>{{:data.title}}</h3>
<p>{{:data.text}}</p>
</script>
<script type="text/x-jsrender" id="j-case2Tpl">
<h3>{{:data.title}}</h3>
<p>{{:data.text}}</p>
</script>
模板數(shù)據(jù)
var condition = {
'case': 1,
'data': {
'title': 'this is first case',
'text': 'case one text'
}
},
//獲取模板
jsRenderTpl = $.templates('#j-specCard'),
//末班與數(shù)據(jù)結(jié)合
finalTpl = jsRenderTpl(condition);
$('.box').html(finalTpl);
使用{{include}}標(biāo)簽引入模板顯得比較語(yǔ)義化,雖然并沒(méi)有什么差別茵乱。除了引入模板茂洒,{{include}}還可以在引入模板的同時(shí)引入對(duì)象或者數(shù)組,來(lái)改變所引入模板的上下文
<script type="text/x-jsrender" id="j-specCard">
{{if case == 1}}
{{include tmpl="#j-case1Tpl" /}}
{{else case == 2}}
{{include data tmpl="#j-case1Tpl" /}}
{{else}}
{{else case == 3}}
{{include data1 tmpl="#j-case2Tpl" /}}
{{else}}
<p>no data</p>
{{/if}}
</script>
<script type="text/x-jsrender" id="j-case1Tpl">
{{!-- for循環(huán)會(huì)默認(rèn)取到傳進(jìn)來(lái)的對(duì)象 使用data.title是訪問(wèn)不到的 --}}
{{!-- 傳進(jìn)來(lái)的對(duì)象必須手動(dòng)循環(huán) --}}
{{for}}
<h3>{{:title}}</h3>
<p>{{:text}}</p>
{{/for}}
{{!--
或者這樣使用
<h3>{{:#data.title}}</h3>
<p>{{:#data.text}}</p>
--}}
</script>
<script type="text/x-jsrender" id="j-case2Tpl">
{{!-- :length 可以獲取當(dāng)前數(shù)組的長(zhǎng)度 --}}
{{:length}}
{{!-- 傳進(jìn)來(lái)的數(shù)組必須手動(dòng)循環(huán) --}}
{{for #data}}
<h3>{{:title}}</h3>
<p>{{:text}}</p>
{{/for}}
{{!--
<h3>{{*:extraData.title}}</h3>
<p>{{*:extraData.text}}</p>
--}}
</script>
傳入的模板數(shù)據(jù)
var condition = {
'case': 2,
'data': {
'title': 'this is first case',
'text': 'case one text'
},
'data1': [
{
'title': 'i am outer fisrt title',
'text': 'it is me,diffrent light'
},
{
'title': 'i am outer second title',
'text': 'it is me,diffrent light'
}
]
};
而引入外部全局對(duì)象或者數(shù)組瓶竭,發(fā)現(xiàn)循環(huán) /遍歷不了督勺,過(guò)后再研究
9、使用{{converters:value}}把value轉(zhuǎn)換成所需要的格式
當(dāng)后端給我們返回的數(shù)據(jù)格式跟頁(yè)面所以展示的格式不一樣的時(shí)候斤贰,我們就需要對(duì)數(shù)據(jù)進(jìn)行轉(zhuǎn)換智哀。比如說(shuō)后端返回時(shí)間的毫秒數(shù),可是頁(yè)面卻要顯示 年-月-日的格式或者是后端返回小寫的字符荧恍,頁(yè)面卻要顯示成大寫的字符瓷叫,這個(gè)時(shí)候轉(zhuǎn)換器就派上用場(chǎng)了。
jsrender提供了api $.views.converters()來(lái)注冊(cè)轉(zhuǎn)換方法块饺。
<script type="text/x-jsrender" id="j-myPersonalInfoTpl">
<div>
<h3>{{upper:name}}</h3>
<p>{{:age}}</p>
</div>
</script>
$.views.converters({
upper: function(val){
return val.toUpperCase();
}
})
//使用jQuery選擇器獲取script標(biāo)簽聲明的jsrender模板并傳入數(shù)據(jù)跟一些方法渲染模板
var myPersonalTpl = $("#j-myPersonalInfoTpl").render(info);
10赞辩、使用{{:~helper(value)}}對(duì)傳入的參數(shù)value做處理
當(dāng)我們拿到的數(shù)據(jù)不符合展示的需求是,我們需要對(duì)數(shù)據(jù)進(jìn)行處理授艰,那么我們可以使用輔助函數(shù),把原始當(dāng)參數(shù)傳入世落,返回我們需要的數(shù)據(jù)淮腾。
jsrender提供了$.views.helper()方法來(lái)注冊(cè)輔助函數(shù)。并使用~當(dāng)前綴來(lái)調(diào)用輔助函數(shù)屉佳。
<script type="text/x-jsrender" id="j-myPersonalInfoTpl">
<div>
<h3>{{:~hello(firstName, lastName)}}</h3>
<p>{{:age}}</p>
</div>
</script>
var info = {
firstName: 'alice',
lastName: 'Jogh',
age: 18
};
$.views.helpers({
hello: function(fisrtName, lastName){
return 'Hello ' + fisrtName + ' ' + lastName;
}
})
//使用jQuery選擇器獲取script標(biāo)簽聲明的jsrender模板并傳入數(shù)據(jù)渲染模板
var myPersonalTpl = $("#j-myPersonalInfoTpl").render(info);
二谷朝、常用API
1. $.templates()
$.templates()方法是用來(lái)注冊(cè)或者編譯模板的,使用的情況有以下幾種武花。
- 把html字符串編譯編譯成模板圆凰。
- 獲取使用script標(biāo)簽聲明的模板,并返回一個(gè)模板對(duì)象
- 把html字符串或者在script標(biāo)簽中聲明的模板注冊(cè)成命名模板
- 獲取之前就存在的命名模板
- 在nodejs中体箕,根據(jù)文件路徑獲取一個(gè)模板對(duì)象
我們正常使用的方式就是使用$.templates()方法把html字符串編譯成模板专钉,返回一個(gè)模板對(duì)象,然后調(diào)用該對(duì)象的render方法并傳入數(shù)據(jù)累铅,就可以得到一份完整的html字符串代碼跃须。比如:
var info = {
name: 'alice',
age: 18
};
//獲取模板
var jsRenderTpl = $.templates('<div><h3>{{:name}}</h3><p>{{:age}}</p></div');
//模板與數(shù)據(jù)結(jié)合
var finalTpl = jsRenderTpl.render(info);
//也可以這樣用 jsRenderTpl(info);
或者我們也可以給模板定義一個(gè)名稱
//定義一個(gè)命名模板
$.templates('myPersonalInfoTpl', '<div><h3>{{:name}}</h3><p>{{:age}}</p></div');
//模板與數(shù)據(jù)結(jié)合
var finalTpl = $.render.myPersonalInfoTpl(info);
當(dāng)然,我們也可以把html字符串單獨(dú)寫在script標(biāo)簽中娃兽,然后根據(jù)id來(lái)獲取
<script type="text/x-jsrender" id="j-myPersonalInfoTpl">
<div>
<h3>{{:name}}</h3>
<p>{{:age}}</p>
</div>
</script>
</body>
<script src="../lib/jquery-1.11.2.min.js"></script>
<script src="../lib/jsrender.js"></script>
<script>
(function(jq, g) {
//定義一個(gè)命名模板
$.templates('myPersonalInfoTpl', '#j-myPersonalInfoTpl');
//模板與數(shù)據(jù)結(jié)合
var finalTpl = $.render.myPersonalInfoTpl(info);
$('.box').html(finalTpl);
})(jQuery, window)
</script>
更想當(dāng)然菇民,還可以在一個(gè)templates()方法里面注冊(cè)多個(gè)命名模板
//定義一個(gè)命名模板
$.templates({
'myPersonalInfoTpl': '#j-myPersonalInfoTpl',
'externalTpl': '<p>this is externalTpl</p>'
});
//模板與數(shù)據(jù)結(jié)合
var finalTpl = $.render.myPersonalInfoTpl(info);
var externalTpl = $.render.externalTpl();
$('.box').html(finalTpl).append(externalTpl);
還可以指定一些只供這個(gè)模板使用的一些方法
<script type="text/x-jsrender" id="j-myPersonalInfoTpl">
<div>
<h3>{{upper:~append(name, ' stev')}}</h3>
<p>{{:age}}</p>
</div>
</script>
//定義一個(gè)命名模板,并指定只供這個(gè)模板使用的轉(zhuǎn)換方法與輔助方法
$.templates("myPersonalInfoTpl", {
markup: "#j-myPersonalInfoTpl",
converters: {
upper: function(val) {
return val.toUpperCase();
}
},
helpers: {
append: function(a, b) {
return a + b;
}
}
});
//模板與數(shù)據(jù)結(jié)合
var finalTpl = $.render.myPersonalInfoTpl(info);
2、渲染模板的render()方法
當(dāng)我們使用$.templates()方法注冊(cè)一個(gè)模板對(duì)象時(shí),最后還是需要把模板對(duì)象跟數(shù)據(jù)結(jié)合得到最終的html字符串的第练,render()的使用方式有以下三種
- 當(dāng)模板對(duì)象myPersonalTpl是使用$.templates()注冊(cè)的模板時(shí)阔馋,只能使用myPersonalTpl.render(data)的方式來(lái)渲染模板
//定義一個(gè)匿名模板
var myPersonalTpl = $.templates("#j-myPersonalInfoTpl");
//模板與數(shù)據(jù)結(jié)合
var finalTpl = myPersonalTpl(info);
- 當(dāng)模板對(duì)象myPersonalTpl是以命名模板的方式注冊(cè)時(shí),需要使用$.render.myPersonalTpl(data)或者$.render['myPersonalTpl'](data)的方式來(lái)渲染模板
//定義一個(gè)命名模板
$.templates("myPersonalInfoTpl","#j-myPersonalInfoTpl");
//模板與數(shù)據(jù)結(jié)合
var finalTpl = $.render.myPersonalInfoTpl(info);
- 當(dāng)使用jQuery娇掏、并且模板是在script標(biāo)簽中聲明時(shí)垦缅,還可以直接使用$("#personTemplate").render(data),并不需要調(diào)用$.templates()方法來(lái)注冊(cè)模板驹碍。
var myHelpers = {
upper: function(val){
return val.toUpperCase();
}
}
//使用jQuery選擇器獲取script標(biāo)簽聲明的jsrender模板并傳入數(shù)據(jù)跟一些方法渲染模板
var myPersonalTpl = $("#j-myPersonalInfoTpl").render(info, myHelpers);
$('.box').html(finalTpl);
我們還可以在渲染模板的同時(shí)壁涎,傳入一些函數(shù)供模板使用
$.render.myTmpl(data, helpersOrContext)
3、 使用$.views.helpers()方法注冊(cè)輔助函數(shù)
當(dāng)我們拿到的數(shù)據(jù)跟頁(yè)面顯示的數(shù)據(jù)有差別志秃、或者是我們需要把原數(shù)據(jù)轉(zhuǎn)化成其他格式的數(shù)據(jù)時(shí)怔球,我們使用使用一些輔助函數(shù)來(lái)實(shí)現(xiàn),jsrender提供了兩種方式浮还,一種是helper函數(shù)竟坛,一種是converters轉(zhuǎn)換器。我們先講輔助函數(shù)helper钧舌。helper方法是以 "~" 為前綴作為方法的標(biāo)示担汤,在加上方法名,然后把值當(dāng)參數(shù)傳進(jìn)去
//example
{{:~myHelperValue}}
{{:~myHelperFunction(name, title)}}
{{for ~myHelperObject.mySortFunction(people, "increasing")}} ... {{/for}}
輔助函數(shù)helper注冊(cè)方式有以下三種:
- 使用$.views.helpers()注冊(cè)全局的helper方法洼冻。
當(dāng)我們需要一些比較通用的方法時(shí)崭歧,可以提取出來(lái)寫到公用的js文件中去,以后就不用重新寫一遍了撞牢。
<div id="box"></div>
<script id="myPersonInfo" type="text/x-jsrender">
<h3>my name is {{:~concat(firstName, lastName)}}</h3>
<p>{{:~util.addPrefix(age)}}</p>
</script>
<script>
var info = {
firstName: 'bolin',
lastName: 'liao',
age: 18
};
// 定義全局的helper方法
$.views.helpers({
concat: function(first , last){
return first + ' ' + last;
},
util: {
prefix: 'age is ',
addPrefix: function(age){
return this.prefix + age;
}
}
});
var html = $('#myPersonInfo').render(info);
$('#box').html(html);
</script>
- 寫局部的輔助方法
當(dāng)我們的某一個(gè)頁(yè)面有多處使用一個(gè)輔助方法率碾,但是又不夠通用,不必寫到common文件去時(shí)屋彪,我們可以寫只供這個(gè)頁(yè)面使用的輔助方法所宰。
// 定義局部的helper方法
var myHelper = {
concat: function(first , last){
return first + ' ' + last;
},
util: {
prefix: 'age is ',
addPrefix: function(age){
return this.prefix + age;
}
}
}
//并在渲染模板的時(shí)候把myHelper當(dāng)做參數(shù)傳進(jìn)去
var html = $('#myPersonInfo').render(info, myHelper);
- 只給特定的模板寫輔助函數(shù),其實(shí)也就是在定義模板的時(shí)候把helper傳進(jìn)去
//注冊(cè)一個(gè)命名模板畜挥,并指定helper方法
$.templates({
myPersonInfo: {
markup: '#myPersonInfo',
helpers: {
concat: function(first , last){
return first + ' ' + last;
},
util: {
prefix: 'age is ',
addPrefix: function(age){
return this.prefix + age;
}
}
}
}
});
//渲染模板,命名模板只能使用$.render調(diào)用
var html = $.render.myPersonInfo(info);
$('#box').html(html);
4仔粥、使用$.views.converters()注冊(cè)轉(zhuǎn)換器
在jsrender中,轉(zhuǎn)換器主要是方便對(duì)數(shù)據(jù)或表達(dá)式的的結(jié)果進(jìn)行處理或者格式化蟹但,jsrender本身自帶了三個(gè)轉(zhuǎn)換器躯泰,比如:
{{html:'<b>bolin</b>'}} //- 對(duì)html標(biāo)簽進(jìn)行編碼,原樣輸出 :<b>bolin</b>
{{>'<b>bolin</b>'}} //同上矮湘,html的別名
{{url:"<_>_\"_'"}} // 對(duì)特殊字符進(jìn)行編碼 基本是 <,>,",'... :%3C_%3E_%22_'
{{attr:value}} //對(duì)標(biāo)簽的屬性值進(jìn)行編碼,也是字符的轉(zhuǎn)換
& → &< → <> → >\x00 → ?' → '" → "` → `= → =
當(dāng)然斟冕,僅僅是這三個(gè)轉(zhuǎn)換時(shí)不夠用的,jsrender提供了自定義轉(zhuǎn)換器的方法缅阳。$.views.converters()磕蛇。比如我想要定義一個(gè)時(shí)間格式化的轉(zhuǎn)換器跟大小寫轉(zhuǎn)換的轉(zhuǎn)換器景描。
<script id="myPersonInfo" type="text/x-jsrender">
<h3>{{upper: 'my name is ' + name}}</h3>
<p>now is {{dateFormat: time}}</p>
</script>
<script>
var info = {
name: 'bolin liao',
time: new Date()
};
//注冊(cè)全局轉(zhuǎn)化器
$.views.converters({
dateFormat: function(val){
var time = new Date();
time.setTime(val || 0); //設(shè)置需要格式化的時(shí)間
return (time.getMonth() + 1) + '月' + time.getDate() + '日';
},
upper: function(val){
console.log(val);
return val.toUpperCase();
}
});
//渲染模板,命名模板只能使用$.render調(diào)用
var html = $('#myPersonInfo').render(info);
$('#box').html(html);
</script>
你會(huì)發(fā)現(xiàn),其實(shí)轉(zhuǎn)換器跟輔助函數(shù)差不多嘛秀撇,只是使用的方法不一樣而已超棺。雖然實(shí)現(xiàn)都差不多,但還是有點(diǎn)區(qū)別的呵燕,轉(zhuǎn)換器也分全局定義跟局部定義棠绘,局部定義的轉(zhuǎn)換只要把模板當(dāng)做參數(shù)傳進(jìn)去就好了,所定義的轉(zhuǎn)換器只能在此模板中生效再扭。
<script id="myPersonInfo" type="text/x-jsrender">
<h3>{{upper: 'my name is ' + name}}</h3>
<p>now is {{dateFormat: time}}</p>
</script>
//myText中的轉(zhuǎn)換器不起作用氧苍,并報(bào)錯(cuò)
<script id="myText" type="text/x-jsrender">
<h3>{{upper: title}}</h3>
<p>now is {{dateFormat: time}}</p>
</script>
//注冊(cè)局部轉(zhuǎn)換器,指定myPersonInfo模板可用
$.views.converters({
dateFormat: function(val){
var time = new Date();
time.setTime(val || 0); //設(shè)置需要格式化的時(shí)間
return (time.getMonth() + 1) + '月' + time.getDate() + '日';
},
upper: function(val){
console.log(val);
return val.toUpperCase();
}
}, $.templates('#myPersonInfo'));
//渲染模板,命名模板只能使用$.render調(diào)用
var html = $('#myPersonInfo').render(info);
$('#box').html(html);
//不可用
var html = $('#myText').render(text);
$('#box').append(html);
除了使用在{{convert:}}標(biāo)簽中之外泛范,還可以在{{if}},{{for}}標(biāo)簽中使用让虐,可以說(shuō)是在任何標(biāo)簽中使用,語(yǔ)法如下:
{{someTag ... convert=...}}
//if語(yǔ)句
{{if convert='inList' item itemList}}...{{/if}}
//for語(yǔ)句
{{for people convert='even'}}
在其他標(biāo)簽中使用時(shí)罢荡,只是需要把轉(zhuǎn)化器賦值給convert赡突,當(dāng)然也可以把輔助方法賦值給convert,比如
{{:name convert=~hlp.bold}}
但是呢区赵,如果你使用{{>name convert=~hlp.bold}}的話惭缰,是會(huì)報(bào)錯(cuò)的,還是老老實(shí)實(shí)使用輔助方法的形式笼才,除了以上的使用方式之外漱受,convert還提供了一些比較好的功能,比如使用this.tagCxt.props可以獲取到標(biāo)簽中定義的屬性患整,使用this.tagCxt.view.data可以獲取到標(biāo)簽中所有的變量拜效。
<script id="myPersonInfo" type="text/x-jsrender">
<h3>{{concat: first last age desc="123" myAttr="test"}}</h3>
</script>
//注冊(cè)局部轉(zhuǎn)換器,指定myPersonInfo模板可用
$.views.converters({
concat: function(){
console.log(this.tagCtx.props);//Object {desc: "123", myAttr: "test"}
console.log(this.tagCtx.view.data);//Object {first: "bolin", last: " liao", age: 18}
}
});
5各谚、使用$.views.tags()注冊(cè)自定義標(biāo)簽
jsrender 提供了一些內(nèi)置的標(biāo)簽,但往往是不夠用的到千,所以提供了$.views.tags()方法來(lái)定義一些比較靈活的標(biāo)簽昌渤。自定義標(biāo)簽比較靈活,能控制憔四、訪問(wèn)的元素也比較多膀息,比如寫在該標(biāo)簽里面的args、props了赵、甚至整個(gè)view model對(duì)象里面的全部數(shù)據(jù)潜支。使用$.views.tags注冊(cè)自定義標(biāo)簽的語(yǔ)法有以下四種
- $.views.tags('myTag', tagOptions); 當(dāng)自定義的標(biāo)簽需要要模板與方法時(shí),一般會(huì)使用這種方式來(lái)注冊(cè)自定義標(biāo)簽柿汛,我們可以在render方法里面處理參數(shù)或者屬性冗酿,然后渲染模板,this.tagCxt對(duì)象下,有當(dāng)前view model的數(shù)據(jù)供訪問(wèn)
<script id="myPersonInfo" type="text/x-jsrender">
{{myPersonInfo name age addPrefix=false /}}
</script>
var info = {
name: 'bolin',
age: 20
};
$.views.tags({
'myPersonInfo': {
render: function(){
//這里可以獲取到自定義標(biāo)簽里面的屬性或者參數(shù)
//可以使用 this.tagCtx.args, this.tagCtx.props, this.tagCtx.view.data 訪問(wèn) view model里面的任何數(shù)據(jù)
console.log(this.tagCtx);
if (this.tagCtx.props.addPrefix) {
return '<h3>Hello, ' + this.tagCtx.args[0] + '</h3><p>' + this.tagCtx.args[1] + '</p>';
}else{
//使用this.tagCtx.render({name:'lbl'})來(lái)渲染定義的模板裁替,并把模板需要的數(shù)據(jù)傳進(jìn)去
return this.tagCtx.render({name:'lbl'}) + '<h3>' + this.tagCtx.args[0] +'</h3><p>' + this.tagCtx.args[1] + '</p>';
}
},
template: '<h2>{{:name}}</h2>'
}
});
當(dāng)然项玛,如果我們不需要模板,那么就只定義一個(gè)方法就好了弱判。
$.views.tags('myPersonInfo', function(){
if (this.tagCtx.props.addPrefix) {
return '<h3>Hello, ' + this.tagCtx.args[0] + '</h3><p>' + this.tagCtx.args[1] + '</p>';
}
});
當(dāng)然襟沮,也可能你的自定義標(biāo)簽只需要模板,并不需要方法來(lái)處理昌腰,那么也是沒(méi)問(wèn)題的开伏,當(dāng)然模板里面也是可以訪問(wèn)各種參數(shù)、屬性的,只是需要使用~tag.tagCtx對(duì)象訪問(wèn)遭商。
<script id="myPersonInfo" type="text/x-jsrender">
{{myPersonInfo name age=age /}}
</script>
$.views.tags('myPersonInfo', {
template: '<h3>{{:~tag.tagCtx.args[0]}}</h3><p>{{:~tag.tagCtx.props.age}}</p>'
});
//也可以這樣
<script id="myPersonInfo" type="text/x-jsrender">
{{myPersonInfo name age addPrefix=false}}
<h3>{{:~tag.tagCtx.args[0]}}</h3>
<p>no info</p>
{{/myPersonInfo}}
</script>
//也可以使用tag.tagCtx.content獲取到自定義標(biāo)簽中的內(nèi)容
$.views.tags('myPersonInfo', {
template: '{{if ~tag.tagCtx.props.addPrefix == true}}\
<h3>Hello, {{:~tag.tagCtx.args[0]}}</h3>\
<p>{{:~tag.tagCtx.props.age}}</p>\
{{else tmpl=~tag.tagCtx.content}}\
{{:~tag.tagCtx.content}}\
{{/if}}'
});
//或者這樣
<script id="teamTemplate" type="text/x-jsrender">
<p><b>{{:title}}</b></p>
<ul>
{{range members start=1 end=2}}
<li>
{{:name}}
</li>
{{/range}}
</ul>
</script>
$.views.tags("range", {
template:
"{{for ~tag.tagCtx.args[0]}}" +
"{{if #index >= ~tag.tagCtx.props.start && #index <= ~tag.tagCtx.props.end}}" +
"{{include tmpl=~tag.tagCtx.content/}}" +
"{{/if}}" +
"{{/for}}"
});
當(dāng)然也可以為某個(gè)模板注冊(cè)私有的自定義標(biāo)簽
$.views.tags({
myTag1: ...,
myTag2: ...
}, parentTemplate);
6固灵、使用$.views.settings.debugMode()開啟調(diào)試模式
當(dāng)我們使用jsrender寫代碼時(shí),難免會(huì)報(bào)一些錯(cuò)株婴,然后直接在控制臺(tái)拋出錯(cuò)誤異常怎虫。但是我們想對(duì)錯(cuò)誤信息做一些處理,比如直接把異常輸出到頁(yè)面困介,或者自定義錯(cuò)誤信息為字符竄大审,或者拋出錯(cuò)誤的時(shí)候,先調(diào)用函數(shù)處理再拋出錯(cuò)誤座哩。jsrender提供了$.views.settings.debugMode()傳入不同的參數(shù)來(lái)改變?nèi)謷伋霎惓5那闆r徒扶。
- false 內(nèi)容不會(huì)被渲染并且在控制臺(tái)拋出異常 (默認(rèn))
- true 拋出的異常會(huì)渲染在頁(yè)面中,在控制臺(tái)中沒(méi)有異常拋出
- "string" 字符串會(huì)替代錯(cuò)誤信息渲染在頁(yè)面中根穷,在控制臺(tái)沒(méi)有異常拋出
- function 在異常拋出之前姜骡,會(huì)先經(jīng)過(guò)傳入的方法處理,如果此方法沒(méi)有return屿良,那么就會(huì)把錯(cuò)誤信息渲染到頁(yè)面中圈澈,如果有return,那么頁(yè)面中就會(huì)渲染return 的信息
$.views.settings.debugMode(function(err){
var errMsg = '';
if(err){
errMsg = 'here has error the err is ' + err;
}
return errMsg;
});
當(dāng)然尘惧,除了為全局處理錯(cuò)誤信息之外康栈,也可以使用onError屬性為某一個(gè)標(biāo)簽定義錯(cuò)誤信息,如果你已經(jīng)在全局設(shè)置了處理錯(cuò)誤信息的方法喷橙,并且傳入的參數(shù)有返回值(上面提到的3跟4)啥么,onError屬性是不會(huì)起作用的
{{:address.street onError="Address unavailable"}}
{{for phones() onError="<em>No phones</em>"}}
{{:address.street onError=name + " has no address"}}
{{:address.street onError=~errorMessages(1, name, 'address')}}
{{myCustomTag ... onError=""}}
$.views.settings.debugMode("this is global err"); //會(huì)覆蓋上面的onError屬性
or
$.views.settings.debugMode(function(err){
var errMsg = '';
if(err){
errMsg = 'here has error the err is ' + err;
}
return errMsg; //如果return 就會(huì)渲染這個(gè),如果不return 就會(huì)渲染onError屬性的值
});
當(dāng)我們使用render()方法渲染模板的時(shí)候贰逾,我們想查看某個(gè)對(duì)象或者某個(gè)屬性的值悬荣,但是并不能在模板中打斷點(diǎn),jsrender提供以下方式在渲染模板的過(guò)程中輸出對(duì)象或者屬性的值
{{dbg expression/}} tag
{{dbg: expression}} convert
{{:~dbg(expression)}} helper
以上的三種方式都會(huì)把值渲染在頁(yè)面疙剑,并在控制臺(tái)中輸出值氯迂,但是呢践叠,如果值是一個(gè)對(duì)象,那么就會(huì)輸出字符串囚戚,比如
JsRender dbg breakpoint: [object Object]
我們需要看對(duì)象里面有什么屬性酵熙,但是卻給我們輸出的是字符串,顯然不方便調(diào)試驰坊,所以我們可以重寫這個(gè)調(diào)試標(biāo)簽,讓輸入值原樣輸出
//重寫dbg調(diào)試模式
$.views.helpers({
dbg: function(val){
try {
console.log(val);
return val;
}catch (e) {
console.log(e);
}
}
});
$.views.converters({
dbg: function(val){
try {
console.log(val);
return val;
}catch (e) {
console.log(e);
}
}
});
$.views.tags('dbg', function(val){
try {
console.log(val);
return val;
}catch (e) {
console.log(e);
}
});
這樣重寫之后匾二,控制臺(tái)輸出變成這樣,就比較方便調(diào)試了
Object {name: "bolin", age: 20}