天天看點

下一代Jquery模闆-----JsRender

在ASP.NET MVC利用PagedList分頁(二)PagedList+Ajax+JsRender中提到了JsRender。JsRedner和JsViews(JsViews是再JsRender基礎上的進一步封裝)被稱為下一代的Jquery模闆,官方位址:https://github.com/BorisMoore/jsrender;https://github.com/BorisMoore/jsviews。Juqrey模闆是一個javascript引擎(抄的、這個東東太高深了),他最直接的作用就是:1、代碼重用,減少代碼量;(貌似還更容易編寫)2、抛棄繁瑣的字元串拼接、提高代碼可見性、簡化維護。

  為什麼需要模闆

  總之,我是寫過無數這樣蛋疼的代碼:

複制代碼

var html = '';

$.each(data.persons, function (i, item) {

     html += "<tr><td>" + item.FirstName + "</td><td><a href='/Person/Edit/"

        + item.PersonID + "'>Edit</a> | <a href='/Person/Details/"

        + item.PersonID + "'>Details</a> | <a href='/Person/Delete/"

        + item.PersonID + "'>Delete</a></td></tr>";

});

$('#XXX').append(html);

複制代碼

  如果覺得這樣還是不明顯,可以參見ASP.NET MVC利用PagedList分頁(二)PagedList+Ajax+JsRender中的第四部分,這樣寫很明顯的壞處就是:這樣的代碼可見性太低,很難維護。或許你幾個月之後再來看你的代碼,你要花半個小時甚至更多才能得出代碼的展示結構。下面來看個JsRender的例子:

複制代碼

//Templates

<script type="text/x-jsrender" id="personListTemplate">

    {{for persons}}

        <tr>

            <td>{{:FirstName}}</td>

            <td>

                <a href="/Person/Edit/{{:PersonID}}">Edit</a> |

                <a href="/Person/Details/{{:PersonID}}">Details</a> |

                <a href="/Person/Delete/{{:PersonID}}">Delete</a>

            </td>

        </tr>

    {{/for}}

</script>

//Render Data

var html  = $("#personListTemplate").render(data);

//Insert into Container

$("#XXX").append(html);

複制代碼

   代碼的結構确實清晰可見了,但是代碼越看越多了。首先,這是錯覺,因為這裡的東東都是嚴格換行了的。其次,這裡省去了item、each等字元複雜字元,貌似更容易編寫了。

  JsRender和Jquery Template

  既然JsRender是下一代Jquery模闆,那麼誰是上一代模闆呢?Jquery Template。Jquery Template的特點這裡就不廢話了,說說JsRedner和Jquery Template的差距:

    1、JsRender渲染非常快,網上說的是“和最快一樣快”(當然我也不知道他到底有多快)。對于簡單的模闆的渲染,JsRender的渲染速度比Js Template可以快20倍。

    2、JsRender對Dom和Jquery不存在任何依賴(注:不依賴并不是說不使用...)。在Jquery Template 必須用$.template(name,'XXX')标記模闆,然後渲染。JsRedner不用,他甚至可以直接渲染字元串。

    3、JsRender和Jquery Template相比,JsRender僅僅需要更少的代碼,2就是一個例子。

  JsRender三要素和行為

  從上面貼的代碼可以看出,JsRender需要三要素:模闆(Template)、容器(Container:簡單。。。)、資料(Data:資料可以使各種js對象:如數組,object等等)。主要行為為:渲染模闆、将渲染結果插入容器(這個太簡單了)。說下渲染模闆先。。。

  JsRender渲染模闆

  1、無需編譯直接渲染: 

var html = $("#XXXXX").render(data); // XXX代表某個腳本标記,也就是上面的<script id="XXX" type="text/x-jsrender">.......</script>

  2、渲染前編譯:

複制代碼

/*A、擷取模闆對象的方式編譯*/

var xxxTemplate = $.templates("#xxxTemplate");//既可以是字元串也可以是腳本标記,B是字元串

var html = xxxTemplate.render(data);

/*B、指定模闆名稱的方式編譯*/

$.templates('xxx','<b>{{:name}}</b>');

$.templates({

  'yyy','<b>{{:name}}</b>',

  'zzz','<b>{{:name}}</b>'

});

var html = $.render.xxx(data);//注意,第B種方式可以同時渲染多個模闆,但是第A種方式不行

複制代碼

   總結一下可以看出:1、無編譯直接渲染的方式無法用于字元串的渲染;渲染前編譯的方式字元串和腳本标記皆可。2、制定模闆名稱的方式編譯可以同時編譯多個模闆,但是擷取模闆對象的方式編譯隻能編譯一個模闆。

  JsRender模闆(Template)

  基本的jsRender标簽:JsRender模闆主要由html标記和jsrender标簽(像上面的{{:XXX}})組成。所有的Jsrender标簽都被兩個大括号包裹,中間既可以是參數也可以使表達式(如:{{:#index}}和{{:#index+1}}),下面看一下一些基本的Jsrender标簽。

描述     例子     輸出

參數firstName的值(未被Html編碼)     {{:firstName}}     Madelyn

參數movie的屬性--releaseYear的值(未被html編碼)     {{:movie.releaseYear}}     1987

比較(表達式,未被html編碼)     {{:movie.releaseYear < 2000}}     true

經html編碼的值(更加安全,但是要耗點記憶體)     {{>movie.name}}     Star Wars: Episode VI: <span style='color:purple;font-style: italic;'>Return of the Jedi</span>

經html編碼的值     {{html:movie.name}}     Star Wars: Episode VI: <span style='color:purple;font-style: italic;'>Return of the Jedi</span>

   jsrender資料周遊:看過ASP.NET MVC利用PagedList分頁(二)PagedList+Ajax+JsRender的童鞋對jsrender的資料周遊相信不會陌生,基本文法如下:

{{for xxx}}

    <li>{{:property of xxx}}</li>

{{/for}}

   有時候想擷取xxx本身怎麼辦呢?如下:

{{for  xxx yyy}}

    <li>{{:#data}}</li>

{{/for}}

  上面的例子要說明兩點:1、for不僅僅可以周遊一組資料,他甚至可以同時周遊兩組和多組資料(強大了吧...)。2、上面的#data就表示xxx和yyy本生。試想一下,如何xxx和yyy都表示一個基本元素(字元串、整數等等、任意交叉)的數組,那麼這個是不是能很好的完成周遊呢?說道#data,不得不提一下#index,#data和#index都是内置的jsrender關鍵字。下面在一個例子:

複制代碼

//Template

{{for #data}}

        <h3>{{:name}}</h3>

        <ul>

        {{for language}}

             <li> {{:#parent.parent.data.name}} is learning {{:title}}</li>

        {{/for}}

        </ul>

{{/for}}

//Data

 var studnets = [

        {

            "name": "Mingjun Tang",

            "language": [{ "title": "English"},{ "title": "Franch"}]

        },

        {

            "name": "Ming Tang",

            "language": [{ "title": "English"}]

        }

];

複制代碼

   周遊時#data充當了students,同時#parent.parent.data.XXX可以用于向上疊代。注意這裡的data并不是student中的屬性額,因為#parent向上疊代後傳回的是一個jsrender對象隻有,#parent.data後才會傳回數組内容。#parent在jsrender叫路徑通路,但是我覺得這裡叫向上疊代還要好些。

  jsrender條件:

複制代碼

{{if  fullprice}}

    html markup

{{else halfprice}}

    html markup

{{else}}

    html markup

{{/if}}

複制代碼

   也可以吧他們扯開用,如:{{if fullprice}}html markup{{/if}}和{{if fullprice}}html markup{{else}}html markup{{/if}}。但是這裡需要注意兩點:

  1、if....else....else表示了if elseif else,這裡的else表示了elseif。

  2、{{if  fullprice}}中的fullprice條件表達式表示的是fullprice不為空。其實還可以有更懂的條件表達式可以應用到這裡來,如下(注意這裡的等于和不等于、、、、):

表達式     舉例     注釋

||     {{ :a || b }}     或

&&     {{ :a && b }}     且

!     {{ :!a }}     非

<= 和>=和 <和 >     {{ :a <= b }}     比較

=== 和 !==     {{ :a === b }}     等于和不等于

  3、在條件表達式中還可以用一些屬性進行比較,如{{if  xxx.length > 50}}等等

  jsrender模闆嵌套:

    在上面一個例子中,嵌套了兩個for循環,試想一下,如果這兩個for循環結構非常複雜或其下還要嵌套一個甚至多個for循環的時候,上面所說的jsrender提高了代碼的可見性和可維護性就不複存在了。于是jsrender也提供了jsrender模闆的嵌套,改寫一下上上面的JsRender模闆:

複制代碼

<script type="text/x-jsrender" id="studentTemplate">

    {{for #data}}

        <h3>{{:name}}</h3>

        <ul>

        {{for language tmpl="#studentLanguageTemplate" /}}

        </ul>

    {{/for}}

</script>

<script type="text/x-jsrender" id="studentLanguageTemplate">

    <li> {{:#parent.parent.data.name}} is learning {{:title}}</li>

</script>

//render

$("#studentList").html($("#studentTemplate").render(studnets));

複制代碼

   這樣就可以避免無限的嵌套下去,隻需要設定{{for}}的tmpl屬性即可。這時,tmpl是一個腳本标記。如果studentLanguageTemplate已經被$.templates()編譯,那麼也可以這麼寫:

複制代碼

<script type="text/x-jsrender" id="studentTemplate">

    {{for #data}}

        <h3>{{:name}}</h3>

        <ul>

        {{for language tmpl="studentLanguageTemplate" /}}

        </ul>

    {{/for}}

</script>

<script type="text/x-jsrender" id="studentLanguageTemplate">

    <li> {{:#parent.parent.data.name}} is learning {{:title}}</li>

</script>

//render

$.templates("studentLanguageTemplate", "#studentLanguageTemplate");

$("#studentList").html($("#studentTemplate").render(studnets));

複制代碼

  上面的templ不再“#XXX”指向一個腳本标記,而是"XXX"指向一個已經标記的腳本标記。(哈哈 說起來還真繞口)。

  OK,基礎的東東就差不多了。不過除了着了,Jsrender還具備良好的可擴充性。後頭在慢慢來看看。。。。。

  補充:

  有些朋友在問jsrender現在是否适合用于項目,看官網介紹:

  Warning: JsRender is close to beta, but not yet officially beta, so there may still be changes to APIs and features in the coming period.

  jsrender雖然接近測試版,但是還不是正式的測試版。是以它的API或一些功能可能還是會有改動。也就是說jsrender的穩定性可能還不是十分确定,是以如果正式的項目還是建議大家使用Jquery Template。