JsRender?常用API
1. $.templates()
$.templates()方法是用來注冊或編譯模板的,使用的情況有以下幾種。
- 把html字符串編譯編譯成模板
- 獲取使用script標簽聲明的模板,并返回一個模板對象
- 把html字符串或者在script標簽中聲明的模板注冊成命名模板
- 獲取之前就存在的命名模板
- 在nodejs中,根據文件路徑獲取一個模板對象
我們正常使用的方式就是使用$.templates()方法把html字符串編譯成模板,返回一個模板對象,然后調用該對象的render方法并傳入數據,就可以得到一份完整的html字符串代碼。比如:
<div id="result"></div><script>var info = {name: 'van',age: 18};//獲取模板var jsRenderTpl = $.templates('<div><h3>{{:name}}</h3><p>{{:age}}</p></div');//模板與數據結合var html = jsRenderTpl.render(info);//也可以這樣用//var html = jsRenderTpl(info); $("#result").html(html);</script>
或者我們也可以給模板定義一個名稱
//定義一個命名模板 $.templates('myPersonalInfoTpl', '<div><h3>{{:name}}</h3><p>{{:age}}</p></div'); //模板與數據結合 var html = $.render.myPersonalInfoTpl(info);
當然,我們也可以把html字符串單獨寫在script標簽中,然后根據id來獲取
<div id="result"></div><script type="text/x-jsrender" id="tmp"><div><h3>{{:name}}</h3><p>{{:age}}</p></div></script><script>var info = {name: 'van',age: 18};//定義一個命名模板 $.templates('myPersonalInfoTpl', '#tmp');//模板與數據結合var html = $.render.myPersonalInfoTpl(info);$('#result').html(html);</script>
更想當然,還可以在一個templates()方法里面注冊多個命名模板
<div id="result"></div><script type="text/x-jsrender" id="tmp"><div><h3>{{:name}}</h3><p>{{:age}}</p></div></script><script>var info = {name: 'van',age: 18};//定義一個命名模板 $.templates({'myPersonalInfoTpl': '#tmp','externalTpl': '<p>this is externalTpl</p>'});//模板與數據結合var finalTpl = $.render.myPersonalInfoTpl(info);var externalTpl = $.render.externalTpl();$('#result').html(finalTpl).append(externalTpl);</script>
還可以指定一些只供這個模板使用的一些方法
<div id="result"></div><script type="text/x-jsrender" id="tml"><div><h3>{{upper:~append(name, ' wu')}}</h3><p>{{:age}}</p></div></script><script>var info = {name: 'van',age: 18};//定義一個命名模板,并指定只供這個模板使用的轉換方法與輔助方法 $.templates("myPersonalInfoTpl", {markup: "#tml",converters: {upper: function (val) {return val.toUpperCase();}},helpers: {append: function (a, b) {return a + b;}}});//模板與數據結合var finalTpl = $.render.myPersonalInfoTpl(info);$('#result').html(finalTpl);</script>
2、渲染模板的render()方法
當我們使用$.templates()方法注冊一個模板對象時,最后還是需要把模板對象跟數據結合得到最終的html字符串的,render()的使用方式有以下三種。 //定義一個匿名模板var myPersonalTpl = $.templates("#tml");//模板與數據結合var finalTpl = myPersonalTpl(info);
當模板對象myPersonalTpl是以命名模板的方式注冊時,需要使用$.render.myPersonalTpl(data)或者$.render['myPersonalTpl'](data)的方式來渲染模板
//定義一個命名模板
$.templates("myPersonalInfoTpl","#tml");
//模板與數據結合
var finalTpl = $.render.myPersonalInfoTpl(info);
當使用jQuery、并且模板是在script標簽中聲明時,還可以直接使用$("#personTemplate").render(data),并不需要調用$.templates()方法來注冊模板。
var myHelpers = {upper: function(val){return val.toUpperCase();}}//使用jQuery選擇器獲取script標簽聲明的jsrender模板,并傳入數據跟一些方法渲染模板。var html = $("#tml").render(data, myHelpers);$('select').html(html);
//example
{{:~myHelperValue}}
{{:~myHelperFunction(name, title)}}
{{for ~myHelperObject.mySortFunction(people, "increasing")}} ... {{/for}}
輔助函數helper注冊方式有以下三種:
- 使用$.views.helpers()注冊全局的helper方法。
當我們需要一些比較通用的方法時,可以提取出來寫到公用的js文件中去,以后就不用重新寫一遍了。
// 定義全局的helper方法 $.views.helpers({concat: function(first , last){return first + ' ' + last;},util: {prefix: 'age is ',addPrefix: function(age){return this.prefix + age;}}});
- 寫局部的輔助方法
當我們的某一個頁面有多處使用一個輔助方法,但是又不夠通用,不必寫到common文件去時,我們可以寫只供這個頁面使用的輔助方法。
// 定義局部的helper方法var myHelper = {concat: function(first , last){return first + ' ' + last;},util: {prefix: 'age is ',addPrefix: function(age){return this.prefix + age;}}}//并在渲染模板的時候把myHelper當做參數傳進去var html = $('#tml').render(data, myHelper);
- 只給特定的模板寫輔助函數,其實也就是在定義模板的時候把helper傳進去
//注冊一個命名模板,并指定helper方法 $.templates({myPersonInfo: {markup: '#tml',helpers: {concat: function(first , last){return first + ' ' + last;},util: {prefix: 'age is ',addPrefix: function(age){return this.prefix + age;}}}}});//渲染模板,命名模板只能使用$.render調用var html = $.render.myPersonInfo(data);$('#box').html(html);
4、使用$.views.converters()注冊轉換器
在jsrender中,轉換器主要是方便對數據或表達式的的結果進行處理或者格式化,jsrender本身自帶了三個轉換器,比如:{{html:'<b>bolin</b>'}} //- 對html標簽進行編碼,原樣輸出 :<b>bolin</b> {{>'<b>bolin</b>'}} //同上,html的別名 {{url:"<_>_\"_'"}} // 對特殊字符進行編碼 基本是 <,>,",'... :%3C_%3E_%22_' {{attr:value}} //對標簽的屬性值進行編碼,也是字符的轉換
當然,僅僅是這三個轉換時不夠用的,jsrender提供了自定義轉換器的方法。$.views.converters()。比如我想要定義一個時間格式化的轉換器跟大小寫轉換的轉換器。
<div id="result"></div><script type="text/x-jsrender" id="myPersonInfo"><h3>{{upper: 'my name is ' + name}}</h3><p>now is {{dateFormat: time}}</p></script><script>var data = {name: 'van',time: new Date()};//注冊全局轉化器 $.views.converters({dateFormat: function (val) {var time = new Date(); return (time.getMonth() + 1) + '月' + time.getDate() + '日';},upper: function (val) {return val.toUpperCase();}});//渲染模板,命名模板只能使用$.render調用var html = $('#myPersonInfo').render(data);$('#result').html(html);</script>
你會發現,其實轉換器跟輔助函數差不多,只是使用的方法不一樣而已。雖然實現都差不多,但還是有點區別的,轉換器也分全局定義跟局部定義,局部定義的轉換只要把模板當做參數傳進去就好了,所定義的轉換器只能在此模板中生效。
//注冊局部轉換器,指定myPersonInfo模板可用 $.views.converters({dateFormat: function (val) {var time = new Date();return (time.getMonth() + 1) + '月' + time.getDate() + '日';},upper: function (val) {console.log(val);return val.toUpperCase();}}, $.templates('#tml'));
除了使用在{{convert:}}標簽中之外,還可以在{{if}},{{for}}標簽中使用,語法如下:
//if語句 {{if convert='inList' }}...{{/if}} //for語句 {{for people convert='even'}}...{{/for}}
在其他標簽中使用時,只是需要把轉化器賦值給convert,當然也可以把輔助方法賦值給convert,比如
{{:name convert=~hlp.bold}}
jsrender 提供了一些內置的標簽,但往往是不夠用的,所以提供了$.views.tags()方法來定義一些比較靈活的標簽。自定義標簽比較靈活,能控制、訪問的元素也比較多,比如寫在該標簽里面的args、props、甚至整個view model對象里面的全部數據。使用$.views.tags注冊自定義標簽的語法有以下四種
- $.views.tags('myTag', tagOptions); 當自定義的標簽需要要模板與方法時,一般會使用這種方式來注冊自定義標簽,我們可以在render方法里面處理參數或者屬性,然后渲染模板,this.tagCxt對象下,有當前view model的數據供訪問
<div id="result"></div><script type="text/x-jsrender" id="tml">{{myPersonInfo name age addPrefix=false?/}}</script><script>var info = {name: 'van',age: 20};$.views.tags({'myPersonInfo': {render: function () {//這里可以獲取到自定義標簽里面的屬性或者參數//可以使用 this.tagCtx.args, this.tagCtx.props, this.tagCtx.view.data 訪問 view model里面的任何數據 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'})來渲染定義的模板,并把模板需要的數據傳進去return this.tagCtx.render({ name: 'lbl' }) + '<h3>' + this.tagCtx.args[0] + '</h3><p>' + this.tagCtx.args[1] + '</p>';}},template: '<h2>{{:name}}</h2>'}});var html = $('#tml').render(info);$('#result').append(html);</script>
當然,如果我們不需要模板,那么就只定義一個方法就好了。
$.views.tags('myPersonInfo', function(){ if (this.tagCtx.props.addPrefix) {return '<h3>Hello, ' + this.tagCtx.args[0] + '</h3><p>' + this.tagCtx.args[1] + '</p>';}});
當然,也可能你的自定義標簽只需要模板,并不需要方法來處理,那么也是沒問題的,當然模板里面也是可以訪問各種參數、屬性的,只是需要使用~tag.tagCtx對象訪問。


<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獲取到自定義標簽中的內容$.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}}"});
當然也可以為某個模板注冊私有的自定義標簽
$.views.tags({myTag1: ...,myTag2: ...}, parentTemplate);
6、使用$.views.settings.debugMode()開啟調試模式
當我們使用jsrender寫代碼時,難免會報一些錯,然后直接在控制臺拋出錯誤異常。但是我們想對錯誤信息做一些處理,比如直接把異常輸出到頁面,或者自定義錯誤信息為字符竄,或者拋出錯誤的時候,先調用函數處理再拋出錯誤。jsrender提供了$.views.settings.debugMode()傳入不同的參數來改變全局拋出異常的情況。
- false 內容不會被渲染并且在控制臺拋出異常 (默認)
- true 拋出的異常會渲染在頁面中,在控制臺中沒有異常拋出
- "string" 字符串會替代錯誤信息渲染在頁面中,在控制臺沒有異常拋出
- function 在異常拋出之前,會先經過傳入的方法處理,如果此方法沒有return,那么就會把錯誤信息渲染到頁面中,如果有return,那么頁面中就會渲染return 的信息
$.views.settings.debugMode(function(err){var errMsg = '';if(err){errMsg = 'here has error the err is ' + err;}return errMsg;});
當然,除了為全局處理錯誤信息之外,也可以使用onError屬性為某一個標簽定義錯誤信息,如果你已經在全局設置了處理錯誤信息的方法,并且傳入的參數有返回值(上面提到的3跟4),onError屬性是不會起作用的
{{: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"); //會覆蓋上面的onError屬性 or$.views.settings.debugMode(function(err){var errMsg = '';if(err){errMsg = 'here has error the err is ' + err;}return errMsg; //如果return 就會渲染這個,如果不return 就會渲染onError屬性的值});
當我們使用render()方法渲染模板的時候,我們想查看某個對象或者某個屬性的值,但是并不能在模板中打斷點,jsrender提供以下方式在渲染模板的過程中輸出對象或者屬性的值
{{dbg expression/}} tag
{{dbg: expression}} convert
{{:~dbg(expression)}} helper
以上的三種方式都會把值渲染在頁面,并在控制臺中輸出值,但是呢,如果值是一個對象,那么就會輸出字符串,比如
JsRender dbg breakpoint: [object Object]
我們需要看對象里面有什么屬性,但是卻給我們輸出的是字符串,顯然不方便調試,所以我們可以重寫這個調試標簽,讓輸入值原樣輸出
//重寫dbg調試模式 $.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);}});
這樣重寫之后,控制臺輸出變成這樣,就比較方便調試了
Object {name: "bolin", age: 20}
?