前端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这篇里有介绍 , 前台模板写成

前端JS模版库kino.razor - 原理流程分析 - 改进版*RazorJs
 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

前端JS模版库kino.razor - 原理流程分析 - 改进版*RazorJs

 编译出的函数会是啥样

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,

前端JS模版库kino.razor - 原理流程分析 - 改进版*RazorJs

这个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),而生成这个函数的速度,都是线性扫描,不见得能快到哪里去,所以不用担心这个。

前端JS模版库kino.razor - 原理流程分析 - 改进版*RazorJs,布布扣,bubuko.com

前端JS模版库kino.razor - 原理流程分析 - 改进版*RazorJs

上一篇:Json-->Newton.Json.dll的使用方法


下一篇:转: 如何实现jQuery的Ajax文件上传