jsRender模板引擎

上一篇最后提到了模板,并尝试自己编写一个最简单版本;有些朋友可能用过 jqtmpl,这是一个基于jquery的模板引擎,不过它已经不再更新了,而且据说渲染速度比较慢。这里介绍另外一个模板引擎:jsRender。个人觉得这些东西学习起来还是很简单的,挑一个看看就行,实际要用到了哪个,官网看看demo也就会用了。之所以选择jsRender,因为它具有以下特点:

  • 简单直观
  • 功能强大
  • 可扩展的
  • 快如闪电

  当然,谁都会自己给自己的产品下这样定义。不过我用完后,确实发现它:简单直观、功能强大、扩展性强;至于快如闪电...,有兴趣的朋友可以测试看看有多快!接下来就让我们学习jsRender的运用,这里用的是1.0版本。

一、基础

  jsRender 三个最重要的概念:模板、容器和数据。最重要的是:view(视图) 是我们定义的模板,上下文是视图所用的对象。

  先来看一下模板的基本标签:{{:}} 和 {{>}}(或{{html:}})。两者都可以输出内容,不过后者是经过html编码的。jsRender有几种方式可以渲染数据:

  假设模板如下:

1
2
3
4
<script type="text/tmp" id="tmp1">
    <p>my name is: {{:name}}</p>
    <p>i am: {{:info.age}} years old</p>
</script>

  数据如下:  

1
2
3
4
var data = {
    name : "tom",
    info : {age : 19}
}

  1.无编译前渲染。直接指定模板。例子:

    var html = $("#tmp1").render(data);
        console.log(html);

  2.编译后渲染。指定模板或字符串。

    2.1 指定模板。效果同1。例子:

      var template = $.templates("#tmp1");
      var html = template.render(data);
      console.log(html);

    2.2 指定模板名称

      2.2.1 传递字符串

        var template = $.templates("tmp1","<b>{{:name}}</b>");
            var html = $.render.tmp1(data);
            console.log(html);

      2.2.2 传递多个模板名称

        var template = $.templates({
            "tmp1":$("#tmp1").html(),
            "tmp2":$("#tmp2").html()
           });
          var html = $.render.tmp1(data);    
          console.log(html);

二、逻辑判断和循环

  2.1 if-else

  语法:{{if condition}} ... {else condition} ... {{else}}... {{/if}}

  注意这里是 if-else-else,而不是 if-else if-else。例子:  

1
2
3
4
5
6
7
8
9
10
11
12
<script type="text/tmp" id="tmp4">
    <p>my name is: {{:name}}</p>
    <p>我是:
    {{if info.age >= 18}}
        成年人
    {{else}}
        未成年
    {{/if}}
    </p>
</script>
var html = $("#tmp4").render(data);
$("#list").html(html);

  2.2 for

  语法:{{for}} ... {{/for}}

  2.2.1 简单for。例子:  

1
2
3
4
5
6
7
8
9
10
11
12
<script type="text/tmp" id="tmp5">
    {{for}}
        <li>id:{{:ID}} name:{{:Name}}</li>
    {{/for}}   
</script>
var arr = [
    { ID: 1, Name: "tom" },
    { ID: 2, Name: "jack" },
    { ID: 3, Name: "lucy"}
];   
var html = $("#tmp5").render(arr);
$("#list").html(html);   

  2.2.2 嵌套for。

  语法:{{for}}...{{for 当前上下文}} ... {{/for}} ... {{/for}}

  被嵌套的for 可以指定要遍历的属性的名称。#getIndex() 和 #data 会在下面提到。例子:  

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<script type="text/tmp" id="tmp7">   
    {{for}}
        <li>
            name:{{:name}}
            <ul>
                {{for hobbies}}
                    <li>{{:#getIndex() + 1}}:{{:#data}}</li>
                {{/for}}
            </ul>
        </li>
    {{/for}}   
</script>
arr = [
     { name: "tom", hobbies: ["篮球""足球"] },
     { name: "jack", hobbies: ["篮球""橄榄球"] },
     { name: "lucy", hobbies: ["游泳""羽毛球"] }
];
var html = $("#tmp7").render(arr);
$("#list").html(html);

  2.2.3 分离for。

  语法:{{for 上下文 tmpl="模板id" /}}

  如果for的逻辑比较复杂,嵌套的for就会让我们的模板变得复杂,维护难度加大;我们可以将for分离,以上面的例子,可以将for放到一个新的模板,然后通过 tmpl属性指定。例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<script type="text/tmp" id="tmp8">   
    {{for}}
        <li>
            name:{{:name}}
            <ul>
                {{for hobbies tmpl="#tmp9" /}}
            </ul>
        </li>
    {{/for}}   
</script>
<script type="text/tmp" id="tmp9">   
    <li>{{:#getIndex() + 1}}:{{:#data}}</li>   
</script>
var html = $("#tmp8").render(arr);
$("#list").html(html);

三、#data、#index、#parent

  开始提到,我们定义的模板就是视图,用到的对象就是上下文。

  #data 当前的上下文,有时候它是很有用的,例如我们返回的是最简单的数组[1,2,3,4],这时没法通过{{:属性}} 的形式去获得,通过{{#data}}即可。另外,可以指定上下文,例如上面的 hobbies,内嵌的for的上下文 #data 就是hobbies,而外部的 #data 是整个arr。

  #index 当前下标。应该用 #getIndex() 去获得。

  #parent 当前上下文所在的视图。parent 属性可以一直往上查找视图,视图的data属性就是当前上下文。例如如果我们要在内嵌的for获得外部的name属性,就可以通过 #parent.parent.data.name 获得。

四、扩展应用

  上面的基本用法已经可以满足大部分需求了。以下几个扩展都是为了分离视图和逻辑的,试想一下,如果我们的视图里还需要大量的逻辑判断或计算,全都写在一起,那会非常麻烦和难以维护。视图最好就是简单的标签,而逻辑都写在js里。jsRender是在视图上进行扩展的。

4.1 自定义标签 Tag

  我们可以把标签里的逻辑移到自定义标签里。

  语法:1.视图 {{"标签名称" 标签参数 附加参数}}
           2.逻辑 $.views.tags({"标签名称":function(参数){this.tagCtx.props.prefix附加参数}}) 

  例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<script type="text/tmp" id="tmp10">
    {{for}}
        <li>
            name:{{:name}}                           
            hobbies: {{format hobbies prefix="@" /}}
        </li>
    {{/for}}        
</script>
$.views.tags({
    "format":function(hobbies){
        if(!hobbies || hobbies.length <= 0){
            return "无";
        }
        var result = "";
        for(var i = 0,length = hobbies.length;i < length; i++){
            result += "," this.tagCtx.props.prefix + hobbies[i];
        }
        result = result.substring(1);
        return result;
    }
})
var html = $("#tmp10").render(arr);
$("#list").html(html);

4.2 转换器 converter

  转换器可以对输出结果进行处理,例如大小写转换等。

  语法:1. 视图 {{"转化器名称":参数}}
          2. js $.views.converters({"转换器名称":function(参数){...}})

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<script type="text/tmp" id="tmp11">   
    {{for}}
        <li>
            Upper Name: {{toUpper:#parent.data.name}}
        </li>
    {{/for}}  
</script>
$.views.converters({
    "toUpper":function(name){
        if(name){
            return name.toUpperCase();
        }
    }
})
var html = $("#tmp11").render(arr);
$("#list").html(html)

4.3 辅助函数 Helper

  扩展函数可以对结果进行处理,逻辑判断等等。

  语法 1. 视图 {{~辅助函数名称(参数)}}
          2. js $.views.helpers({"辅助函数名称":function(参数){}})

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<script type="text/tmp" id="tmp12">   
    {{for}}
        <li>
            name: {{:name}}
            hobbies: {{:~concat(hobbies)}}
        </li>
    {{/for}}  
</script>
$.views.helpers({
    "concat":function(hobbies){           
        if(!hobbies || hobbies.length <= 0){
            return "";
        }
        var result = "";
        for(var i = 0,length = hobbies.length;i < length;i++){
            result += "&&" + hobbies[i];
        }
        return result.substring(2);
    }
})
var html = $("#tmp12").render(arr);
$("#list").html(html);

五、总结

  jsRender还是比较新的,使用起来也比较方便。不过我们看到我们的数据和页面之间是一个单向的过程,而且是一次性的单向;也就是当我们的数据改变时,视图不能自动更新,而界面的数据改变时,实际数据也不能自动改变。设想一下,如果数据和视图是双向的,其中一个改变,都可以自动更新另外一个,那不就最好了,我们只需要操作数据,不需要操作dom了。这就是mvvm的机制,前端的mvvm框架有很多:knockout、angular等。下一篇将开始介绍knockout。

 
分类: knockout
标签: knockout

jsRender模板引擎的更多相关文章

  1. knockoutJS学习笔记02:jsRender模板引擎

    上一篇最后提到了模板,并尝试自己编写一个最简单版本:有些朋友可能用过 jqtmpl,这是一个基于jquery的模板引擎,不过它已经不再更新了,而且据说渲染速度比较慢.这里介绍另外一个模板引擎:jsRe ...

  2. JsRender (js模板引擎)

    最近学习了一下Jsrender模板渲染工具,非常不错,功能比较强大,官网说他是“简单直观 功能强大 可扩展的 快如闪电”确实如此.总结一下!! jsRender 三个最重要的概念:模板.容器和数据. ...

  3. 如何选择Javascript模板引擎(javascript template engine)?

    译者 jjfat 日期:2012-9-17  来源: GBin1.com 随着前端开发的密集度越来越高,Ajax和JSON的使用越来越频繁,大家肯定免不了在前台开发中大量的使用标签,常见到的例子如下: ...

  4. javascript模板引擎Mustache

    Mustache(英文本意:触须,胡须)是基于JavaScript实现的模版引擎,类似于JQuery Template,但是这个模版更加的轻量级,语法更加的简单易用,很容易上手. 下载:https:/ ...

  5. 高级 JsRender 模板功能

    转自:http://msdn.microsoft.com/zh-cn/magazine/hh975379.aspx 尽管模板很强大,但有时模板引擎提供的现成标准功能无法满足您的需求. 您可能要转换数据 ...

  6. Web模板引擎—Mustache

    Web模板引擎——Mustache 2012年9月12日 BY BELL·12 COMMENTS Web 模板引擎是为了使用户界面与业务数据(内容)分离而产生的,它可以生成特定格式的文档,通常是标准的 ...

  7. 10 个强大的JavaScript / jQuery 模板引擎推荐

    模板引擎是为了使用户界面与业务数据(内容)分离而产生的,它可以生成特定格式的文档.由于在开发过程中,网站或应用程序的界面与数据实现分离,大大提升了开发效率,良好的设计也使得代码重用变得更加容易. 本文 ...

  8. JavaScript学习笔记(一)——延迟对象、跨域、模板引擎、弹出层、AJAX示例

    一.AJAX示例 AJAX全称为“Asynchronous JavaScript And XML”(异步JavaScript和XML) 是指一种创建交互式网页应用的开发技术.改善用户体验,实现无刷新效 ...

  9. Handlebars 模板引擎之前后端用法

    前言 不知不觉间,居然已经这么久没有写博客了,坚持还真是世界上最难的事情啊. 不过我最近也没闲着,辞工换工.恋爱失恋.深圳北京都经历了一番,这有起有落的生活实在是太刺激了,就如拿着两把菜刀剁洋葱一样, ...

随机推荐

  1. 工程PMO工作

     算起来,这是第一次以项目PMO人员的身份參与项目.尽管非常可惜没有从头參与,也没有參与到项目结束.仅仅有短短的两个月,但对项目PMO也可略窥一斑.如今就当个流水账写一写吧. 进项目组的时候,是中 ...

  2. Robotium原则的实施源代码分析

    从前面的章节<Robotium源代码分析之Instrumentation进阶>中我们了解到了Robotium所基于的Instrumentation的一些进阶基础.比方它注入事件的原理等,但 ...

  3. 程序设计实践C++ 程序代写(QQ 928900200)

    程序设计实践 采用C++作为编程语言. 设计开发一个“学生信息”管理系统.该系统模拟数据库管理系统(DBMS)的功能,为用户提供数据存储.查找的能力. 该系统存储的学生信息包括: 学号.姓名.性别.语 ...

  4. 尝到awk

    我前几天写的sed,这个时候继续了解它的兄弟,awk,两者都使用,一种感觉.既可以用来处理场.假设你想要做文本处理.sed删除.匹配,一些频繁更换使用,假设每一行文本,你想深入,一些每行和列处理的,例 ...

  5. python基础课程_学习笔记15:标准库:有些收藏夹——fileinput

    标准库:有些收藏夹 fileinput 重要功能 性能 叙述性说明 input([files[,inplace[,backup]]) 便于遍历多个输入流中的行 filename() 返回当前文件的名称 ...

  6. Google Maps Android API v2 (4)- 地图类型

    地图类型 地图内的谷歌地图的Android API的种类有很多.地图的类型管辖地图的整体代表性.例如,地图集通常包含政治地图,专注于显示边界和道路地图,显示了一个城市或地区的所有道路. Android ...

  7. WPF中对三维模型的控制

    原文:WPF中对三维模型的控制 (以下选自南开大学出版社出版的<WPF和Silverlight教程>) 3Dmax中的建模模型可以导出为obj文件格式,将此文件导入WPF项目中,由WPF完 ...

  8. SQL Server数据库视图

    1:什么是视图 2:视图和查询的区别 3:视图的优点 4:如何创建和管理视图 5:如何通过视图修改基本表的数据 6:如何通过视图实现数据的安全性 A:什么是视图: 视图(view):从一个或几个基本表 ...

  9. python正文(两)

    在本文中,我读了记录和总结<Python标准库>一本书,本节课文的学习和理解. 事实上,在Python于,使用一些方法这段文字是一回事,尤其是经常使用.在一般情况下,会用String这样的 ...

  10. C++笔试面试总结

    手游广州某公司书面今天接受采访时.刚进去中午1中场休息.他们公司谁刚刚醒来,一个冷漠打牌,然后去上班.瞬间,这些公司有没有什么好印象,压抑. 接着快2点的时候.发了一份笔试题.大部分题目均在网上的&l ...