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

1.前言

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

 

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

 

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

怎麼使用https://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         <p>@(i)</p>

10     }

11 </script>

復制代碼

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

 

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

 

在拿到templateString之後,模板引擎會一個字一個字的掃描,處理,碰到@{}這樣的代碼塊,它就需要在一個context中執行,以保存其中的變量呢,碰到普通的string,像<p>這種,直接放到結果集中,對於@(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模式,就是可以直接寫<p>引用變量要寫@符號

    for(var i=0;i<10;i++)

    {

        //在循環內部,String 輸出內容,我們構建一個數組result 來裝 要生成的內容

 

         //碰到<p>

         result.push("<p>");

         //碰到@(i)

         result.push(i);//變量,在當前context取值,並放到生成結果集中

         //碰到</p>,放到result

         result.push("</p>")

    }

}

 

這樣就達到瞭循環的目的。可是這樣的期望函數咋生成???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的直接使用p作為模板的方法

例如直接在p中寫

 

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

 

     other template ….

 

</p>

 

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

 

另外一種

 

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

 

<p>@item.age</p>

 

</p>

 

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

 

 

 

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

 

4.關於渲染速度…

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

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *