在下一代Jquery模板-----JsRender中提到,JsRender由Jsrender標簽+Html標簽組成。說道Html,就很容易想起xml,xml和html一個顯著的不同點就在於:xml是可擴展標記語言,也就是說,xml可以根據你的需要自己定義標簽(當讓要符合良好的xml格式),這就很方便了(當然不是說html不好,試想如果大家都用自己定義的標簽來展示網頁結構,那不慘了)。JsRender可以不勒?可以。除了下一代Jquery模板-----JsRender說的{{:}}、{{>}}、{{for /}}、{{if /}}等之外,還可以自己定制Jsrender標簽、轉換器、輔助函數等。這些都使JsRender具有良好的擴展性。
問題糾正
在下一代Jquery模板-----JsRender中,說道#parent關鍵字的時候,我說是#perent返回的是一個JsRender對象,這樣說是不准確的。其實#parent返回的是當前視圖#view,通過#view.data可以訪問當前視圖的上下文數據---#data。
<li><b>{{:#view.data.name}}</b>({{:#data.releaseYear}})</li>//{{:#view.data.XXX}}就相當於{{:#data.XXX}}
自定義JsRender標簽
在Jsrender中,提供了很多進行數據綁定、邏輯處理等的標簽,如{{for /}}、{{if /}}等等,但是當面臨復雜的邏輯處理時候(當然我們不可能把復雜的邏輯處理放在客戶端,那么系統的擴展性就不是很理想了,所以個人感覺掌握Jsrender提供的標簽已經夠用了),我們肯定會被{{for /}}、{{if /}}弄的焦頭爛額,因為這樣模板本省的可見性已經降低了,或許后期維護的時候,還需要花大量的時間去閱讀模板,事倍功半了。所以,Jsrender提供了自定義標簽,降低邏輯和表現之間的耦合。
//使用自定義Jsrender標簽:{{tagName Entity params=values}} <li>{{:Name}}({{format Languages saySomething = "The analysis of languages:" /}})</li> ///定義Jsrender自定義標簽:$.views.tags({tagName:function(Entity){XXX}}) $.views.tags({ format: function (Languages) { var ret = ""; if (this.props.saySomething) { ret += this.props.saySomething; } for (var i = 0; i < Languages.length; i++) { ret += Languages[i]; if (i == Languages.length - 2) { ret += " and "; } else if (i < Languages.length - 2) { ret += " , "; } } return ret; } });
從上面的東東可以看到,JsRender自定義標簽需要注意兩點:
1、Jsrender自定義標簽的方法:$.views.tags({tagName:function(Entity){XXX}})。自定義標簽的調用:{{tagName Entity params=values}}。可以看到實體(姑且這么說哈)既是需要渲染的屬性,和{{:Name}}中的Name一樣。
2、實體后還可以跟參數,格式如下:ParamName = value,在$.views.tags的定義時,通過this.props.XXX獲取。
試想一下,當面對比較復雜的邏輯時候,如果用自定義標簽來解決,那模板的可見性是不是更高了呢?這就可以看到模板的好處。而且面臨相對復雜的邏輯,當這個自定義標簽在整個應用程序中使用的時候,Jsrender的重用性也進一步體現了。
JsRender轉換器
表面上看,JsRender轉換器可以看做是自定義JsRender的一個補充,因為除了除了語法不通之外,唯一不通之處便是:JsRender自定義標簽可以指定參數,但是轉換器不能。這是由他們的本質決定的。轉換器主要負責數據的轉換,例如將字符串全部轉換為大些。。(貌似說的不清不楚的,看下面例子就懂了)等等,但是自定義標簽和{{for/}}一樣,是標簽,所以可以指定參數。(不清不楚啊。。。看看下面例子。。。慢慢體會啊。。。。)。一般情況,我優先選擇轉換器,因為更輕量級些(僅限於感覺。。。。)
//轉換器調用:{{converterName:XXX}} <li>{{format:#data}}</li> //轉換器定義:$.views.converters({converterName:function{XXX}}) var names = ["AAA", 1, true]; $.views.converters({ format: function (name) { return name + " is a " + typeof (name); } }); var nameHtml = $("#nameTemplate").render(names); $("#nameList").html(nameHtml);
JsRender輔助函數
除了JsRender自定義標簽和轉換器,JsRedner還提供了輔助函數。輔助函數的定義、調用和自定義標簽以及轉換器都差不多,當然我也不知道為什么會有個這個東東存在。貌似這三個東東分別標志着:標簽、數據轉換、函數三個基本上的擴展。廢話少說,先看看輔助函數的定義和調用:
//輔助函數應用:{{~FuncName(params)}} <li>{{:name}}{{if ~nextToLast()}} and {{else ~notLast()}}, {{/if}}</li> //定義:$.views.helpers({funcName:funciton(params){XXX}}) $.views.helpers({ nextToLast: function() { var view = this; return view.index === view.data.length - 2; }, notLast: function() { var view = this; return view.index !== view.data.length - 1; } });
這里需要注意的三點:1、我們可以同時定義多個自定義標簽、轉換器和輔助函數(如上)。2、輔助函數、轉換器、自定義標簽中的this,表示的是當前視圖。所以需要獲取數據的時候需要this.data.XXX(parent、index等等)。3、注意這里不能直接 return this。因為這個時候返回的是當前視圖對象,在模板中無法直接解析,最好的處理方案是利用this.renderContent(view)返回數據上下文對象。
ok,終於是寫完了。這篇博客主要想證明,JsRedner不僅渲染性能上有很大的提升,而且JsRender具備良好的擴展性。我們可以通過自定義JsRender標簽、轉換器、輔助函數輕松的擴展復雜的邏輯和標簽。而且這里的應用都相對簡單,JsRender可以處理各種復雜的邏輯,詳細的還是參考官網上:https://github.com/BorisMoore/jsrender 。不足之處,繼續改進。