以前的一个项目里面就有用到这个前台的渲染模版,当时挺忙的也没时间抽空总结一下,恰好上周项目里又用到这个轻量型的渲染模版,真心感受很好用,所以就总结一下使用心得,算是一个入门级别的指引吧。javascript
Mustache是基于JavaScript实现的模版引擎,相似于jQuery Template,可是这个模版更加的轻量级,语法更加的简单易用,很容易上手。html
下面就具体讲一下Mustache的使用。在开始讲以前,须要先从Git hub上获取相关的mustache.js文件,获取文件以后,新建一个解决方案,目录以下:java
而后就开始具体的使用,首先须要在页面的head标签内引用Jquery.js 和Mustache.js两个脚本文件,主要有如下几个方面(如下演示的方法均在head标签中的script代码块中):ajax
l 代码示例:json
$(function () { var user = { name: "Olive", age: 23, sex: "girl" }; var template = "My name is {{name}} ,I'm {{age}} ,Sex is {{sex}}"; var view = Mustache.render(template, user); $("#user_info").html(view); }
l 页面呈现效果:数组
My name is Olive ,I'm 23 ,Sex is girl
l 语法解释:app
i. Mustache的语法很简单,用两个大括号标记要绑定的字段便可,“{{}}”;函数
ii. 大括号内的字段名称要和Mustache.render方法中的第二个参数中的对象的属性名一致this
iii. 主要的渲染方法为Mustache.render,该方法有两个参数,第一个为要渲染的模版,也就是上例中的template,第二个就是数据源也就是上例中的user对象url
l 代码示例:
var users = { result: [{ name: "Only", age: 24, sex: "boy" }, { name: "for", age: 24, sex: "boy" }, { name: "Olive", age: 23, sex: "girl" } ] }; var template = "<div><table cellpadding=0 cellspacing=0 class='tb' ><tr><td>Name</td><td>Age</td><td>Sex</td></tr>{{#result}}<tr><td>{{name}}</td><td>{{age}}</td><td>{{sex}}</td></tr>{{/result}}</table><div>"; var views = Mustache.render(template, users); $("#user_info").html(views);
l 页面呈现效果:
Name Age Sex Only 24 boy for 24 boy Olive 23 girl
l 语法解释:
i. 对于对象数据Mustache也有其特殊的语法:{{#}}{{/}},若是所给定的数据源是一个对象数组,则可使用该语法,很方便的用来循环展现。
ii. 其中{{#}}标记表示从该标记之后的内容所有都要循环展现
iii. {{/}}标记表示循环结束。这种状况多用于table行的展现。
l 代码示例:
var users = { result: [{ name: null, age: 24, sex: "boy" }, { name: "for", age: 24, sex: "boy" }, { name: "Olive", age: 23, sex: "girl" } ] }; var template = "<div><table cellpadding=0 cellspacing=0 class='tb' ><tr><td>Name</td><td>Age</td><td>Sex</td></tr>{{#result}}<tr><td>{{#name}}{{name}}</td><td>{{age}}</td><td>{{sex}}{{/name}}</td></tr>{{/result}}</table><div>"; var views = Mustache.render(template, users); $("#user_info").html(views);
l 页面呈现效果:
Name Age Sex for 24 boy Olive 23 girl
l 语法解释:
i. 上边咱们有讲到{{#}}{{/}}这样的语法,除了上边的循环遍历以外,它还有另外的一层意思就是判空,若是{{#}}中的值为null或false或undefine则其标记内的内容则不展示
ii. 在代码示例中,users对象中的第一个对象名为null,因此在展现时,该条用户信息没有被展现。
iii. 有了判空的方法固然还有与之相反的方法{{^}},该方法表示的意思与{{#}}意思相反。
l 代码示例:
var user = { name: "<h1>Olive</h1>" }; var template = "my name is {{&name}}"; var view = Mustache.render(template, user); $("#user_info").html(view);
l 页面呈现效果:
my name is Olive
若是不在{{}}中加&,则效果以下:
var user = { name: "<h1>Olive</h1>" }; var template = "my name is {{name}}"; var view = Mustache.render(template, user); $("#user_info").html(view);
l 页面呈现效果:
my name is <h1>Olive</h1>
l 语法解释:
i. 在某些时候,咱们要绑定的数据源中可能会有一些html标记,若是单纯的采用{{}}这种方式来绑定的话,默认的会将html标记转义。为了解决防止绑定字段中的内容被转移咱们能够这样作{{&}},这样就能够防止转义。
代码实例:
例1:
var view = { title: 'YZF', cacl: function () { return 6 + 4; } }; $("#user_info").html(Mustache.render("{{title}} spends {{cacl}}", view));
l 页面呈现效果:
YZF spends 10
结论:
能够很明显的看出Mustache模板的语法,只须要使用{{和}}包含起来就能够了,里面放上对象的名称。
经过本示例也能够看出,若是指定的属性为函数的时候,不会输出函数里面的内容,而是先执行函数,而后将返回的结果显示出来。
例2:
var view = { name: "YZF", company: "<b>ninesoft</b>" }; $("#user_info").html(Mustache.render("{{name}} <br /> {{company}} <br />{{{company}}}<br/>{{&company}}", view));
l 页面呈现效果:
YZF <b>ninesoft</b> ninesoft ninesoft
结论:
经过这个示例能够看出Mustache默认是会将值里面的html标记进行转义的,可是有时候咱们并不须要。
因此这里咱们可使用{{{和}}}包含起来,或者是{{&和}}包含,那么Mustache就不会转义里面的html标记。
例3:
var view = { "name": { first: "Y", second: "zf" }, "age": 21 }; $("#user_info").html(Mustache.render("{{name.first}}{{name.second}} age is {{age}}", view));
l 页面呈现效果:
Yzf age is 21
结论:
绑定子属性,仅仅只须要经过.来使用子属性便可。
例4:
var view = { person: false }; $("#user_info").html(Mustache.render("eff{{#person}}abc{{/person}}", view));
l 页面呈现效果:
eff
结论:
问题老是不断,若是咱们还须要可以根据咱们给的值,决定是否渲染某个部分。
那么如今就能够解决这个问题,固然还要提示的就是不只仅是false会致使不渲染指定部分。
null,空数组,0,空字符串同样有效。语法上面比较简单,就是使用{{#key}} ... {{/key}}
来控制中间的内容。
例5:
var view = { stooges: [ { "name": "Moe" }, { "name": "Larry" }, { "name": "Curly" } ] }; $("#user_info").html(Mustache.render("{{#stooges}}{{name}}<br />{{/stooges}}", view));
l 页面呈现效果:
Moe Larry Curly
结论:
仅仅学会上面的方式,大部分地方你都解决了,可是仍是会出现麻烦的地方。
就是循环输出,若是你一个一个写,相信会很烦躁,固然Mustache不会让咱们失望,
它也给出了如何循环输出的方式,这里是将一个由对象组成的数组输出,若是咱们
输出的是数组,就须要使用{{.}}来替代{{name}}。
例6:
var view = { "beatles": [ { "firstname": "Johh", "lastname": "Lennon" }, { "firstname": "Paul", "lastname": "McCartney" } ], "name": function () { return this.firstname + this.lastname; } }; $("#user_info").html(Mustache.render("{{#beatles}}{{name}}<br />{{/beatles}}", view));
l 页面呈现效果:
JohhLennon PaulMcCartney
结论:
循环输出是有了,可是咱们还想后期进行加工。那么这个彻底符合你的须要,由于Mustache会将
数组中的值传递给你的函数,输出你函数返回的值。这里咱们能够看到最外层是数组,只要在里面
使用函数那么外层的数组就会做为这个函数的参数传递进去。
例7:
var view = { "name": "Tater", "bold": function () { return function (text, render) { return render(text) + "<br />"; } } } $("#user_info").html(Mustache.render("{{#bold}}{{name}}{{/bold}}", view));
l 页面呈现效果:
Tater
结论:
上面咱们都是用的变量做为节,那么咱们如今用函数做为节,会有什么效果呢。
它会调用咱们函数返回的函数,将节中间的原始字符串做为第一个参数,默认
的解释器做为第二个参数,那么咱们就能够自行加工。
例8:
var view = { "repos": [] }; $("#user_info").html(Mustache.render("{{#repos}}{{.}}{{/repos}}{{^repos}}no repos{{/repos}}", view));
l 页面呈现效果:
no repos
结论:
上面咱们也用节,可是仅仅只能选择是否输出某个部分。因此这里咱们弥补一下。
若是咱们使用了{{^和}}来定义节的话,那么这个部分只会在里面的值为空,null,
空数组,空字符串的时候才会显示。那么咱们就能够实现了if else的效果了。
例9:
var view = { names: [ { "name": "y" }, { "name": "z" }, { "name": "f" } ] }; var base = "<h2>Names</h2>{{#names}}{{>user}}{{/names}}"; var name = "<b>{{name}}</b>"; $("#user_info").html(Mustache.render(base, view, { user: name }));
l 页面呈现效果:
Names yzf
结论:
Mustache虽然节约了不少时间,可是咱们定义了不少模板,可是彼此之间没法互相嵌套使用,也会形成繁琐。
因此这里咱们还要介绍如何定义部分模板,用来在其余模板里面使用,这里使用其余模板的方式仅仅是{{>templetename}}。
最大的不一样就是Mustache.render方法有了第三个参数。
例10:
HTML中:
其中deptList为后台传过来的LIST集合,想要达到的效果,在<ol>标签中根据deptList集合来递归生动态生成多个<li>元素
<script id="deptListTemplate" type="x-tmpl-mustache"> <ol class="dd-list"> {{#deptList}} <li class="dd-item dd2-item dept-name" id="dept_{{id}}" href="javascript:void(0)" data-id="{{id}}"> <div class="dd2-content" style="cursor:pointer;"> {{name}} <span style="float:right;"> <a class="green dept-edit" href="#" data-id="{{id}}" > <i class="ace-icon fa fa-pencil bigger-100"></i> </a> <a class="red dept-delete" href="#" data-id="{{id}}" data-name="{{name}}"> <i class="ace-icon fa fa-trash-o bigger-100"></i> </a> </span> </div> </li> {{/deptList}} </ol> </script>
JS:
$(function() { var deptList; // 存储树形部门列表 var deptMap = {}; // 存储map格式的部门信息 var deptListTemplate = $('#deptListTemplate').html(); Mustache.parse(deptListTemplate); loadDeptTree(); /*加载部门树*/ function loadDeptTree() { $.ajax({ url: "/sys/dept/tree.json", success : function (result) { //成功返回数据ret为TRUE deptList = result.data; var rendered = Mustache.render(deptListTemplate, {deptList: result.data}); $("#deptList").html(rendered); recursiveRenderDept(result.data); } }) } // 递归渲染部门树 function recursiveRenderDept(deptList) { if(deptList && deptList.length > 0) { $(deptList).each(function (i, dept) { deptMap[dept.id] = dept; if (dept.deptList.length > 0) { var rendered = Mustache.render(deptListTemplate, {deptList: dept.deptList}); $("#dept_" + dept.id).append(rendered); recursiveRenderDept(dept.deptList); } }) } } });
例11:
Mustache.parse(template); //其余代码 Mustache.render(template,view);
结论:
模板既然有好处,也有坏处。就是编译模板须要时间,因此在咱们已知会使用某个模板的前提下,咱们能够预先编译好这个模板,以便后面的使用。