前端JS模版庫kino.razor - 原理流程分析 - 改進版輪子RazorJs


1.前言

從后台獲取數據,在前端JS里面拼接字符串,不累嗎?敢不敢找一款前端使使。。。

現在這種模板庫比較多了,我用過的jquery-template 、JsRender 、聽說過的一堆,還有各種MVC庫里面帶的各種模板庫,之前看到有人介紹kino.razor這個,一看源代碼,就幾百行,以前用過的那些template engine,好奇怎么出來的。就借這個機會研究研究,自己模仿者造一個。它源碼少啊。。。

2.kino.razor模版庫原理,流程分析

怎么使用http://www.cnblogs.com/Music/p/kino-razor.html這篇里有介紹 , 前台模板寫成

 1 <script type="text/template">
 2     @{
 3         //code block...
 4         var data=10;
 5     }
 6 
 7     @for(var i=10;i<data;i++)
 8     {
 9         <div>@(i)</div>
10     }
11 </script>
View Code

這種js代碼與html混在一起的,是怎么實現的呢。。。

首先分析這種template要認識到,有兩種模式,即js code 模式,和 html代碼模式。在code模式中,@{ code block}這種,就是要執行的代碼,不會產生模版生成的內容,另一種就是引用變量了,在<div>@(variable)</div>這里,這個@(variable)同<div> </div>一樣,會被生成到 模板引擎 生成的html中。這么說有點抽象。所以說,有三種狀態1.代碼塊 2.普通string,最后生成到html 3.變量,需要執行並申城到html里

在拿到templateString之后,模板引擎會一個字一個字的掃描,處理,碰到@{}這樣的代碼塊,它就需要在一個context中執行,以保存其中的變量呢,碰到普通的string,像<div>這種,直接放到結果集中,對於@(variable)需要在這個context中解釋一下,這個值說不定就是前面code block中聲明的,再放到結果集中。

就像這樣一個 模板,可以使用kino.razor(template,model);這個model對象是傳進去的,要被模板利用,就同樣需要這樣的context,那么誰來提供這樣一個context呢???我是看了源碼,這個模板字符串最終會被編譯成一個函數,就是var func=某種方法(string template),將string變成一個function,然后這個model,傳給func,即func(model)就會得到輸出的html

 編譯出的函數會是啥樣

function func(model){
     var result=[];
    //在@{}這樣的code block中全是code,直接放到 這里運行
    var data=10;

    //@for(){   }
   在for while循環里面默認是String模式,就是可以直接寫<div>引用變量要寫@符號
    for(var i=0;i<10;i++)
    {
        //在循環內部,String 輸出內容,我們構建一個數組result 來裝 要生成的內容

         //碰到<div>
         result.push("<div>");
         //碰到@(i)
         result.push(i);//變量,在當前context取值,並放到生成結果集中
         //碰到</div>,放到result
         result.push("</div>")
    }
}

這樣就達到了循環的目的。可是這樣的期望函數咋生成???JS里面有 new Function(parameter0,...parametern,最后一個參數為函數體)

我們只要能生成函數體就可以了。生成那個函數體functionContent,以字符串形式呈現,需要我們根據template string的狀態,是code block,還是string,還是變量variable,往functionContent添加不同的語句,最后構成函數func,調用func(model)就返回了我們函數體中的result。在kino.razor中用SegmentHelper.parse將templateString轉化為一個一個segmrnt,

這個segment就是以狀態區分的內容,content 即內容,type 即類型,狀態

用ContentHelper將這個segment數組,轉變成functionContent,進而返回一個參數為model的func。

That‘s all。

 3.RazorJs.js

搞清楚那個庫的原理,和流程,自己寫一個也就不是太難,模仿照着做就行。我自己搗鼓着做了一個RazorJs,將能簡化的簡化,我不想要的功能就沒做,例如kino.razor中@variable是可行的,即不加小括號'()'也可以,我就覺得不直觀,就沒有實現。在這個RazorJs中引用變量必須要用小括號括起來,如@(variable),添加了一些和jquery相關的方法,當然在沒有jquery的情況下也是可以使用razor.render 和 compile方法。修改model為ViewBag。第一遍源碼跟kino.razor太像,而且寫完第二天,發現支持的while循環沒有意義,不支持在while內部寫code block例如while(i>0) i--;這個i--沒地寫,故重新整理思路,重新寫了份,原來的更名RazorJs.0.1.js。

 

添加類似angularJS的ng-repeat的直接使用div作為模板的方法
例如直接在div中寫

<div razor-template razor-for="var i = 0;i<10; i++">

     other template ....

</div>

使用$(selector).renderNode(ViewBag)來使render,並show出來,寫上了razor-template在dom ready的時候會被隱藏

另外一種

<div razor-repeat="item in items" razor-template>

<div>@item.age</div>

</div>

這種跟C#里面寫的foreach(var item in items)是一致的,這種div使用$(selector).renderRepeat(ViewBag),來使模板變為字符串

 

還有更多的擴展用法可以看csdn code 地址https://code.csdn.net/magicdawn/razorjs。那些markdown正在慢慢的寫。源碼注釋超級多,別見怪。

4.關於渲染速度...

在上面我們知道,這些其實是編譯成了一個函數 , 所以在那些測試中所謂的千次萬次render是沒有意義的,真正的次數多的render,可以先compile出來func函數,再自己調用func(ViewBag),而生成這個函數的速度,都是線性掃描,不見得能快到哪里去,所以不用擔心這個。


免責聲明!

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



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