剑客
关注科技互联网

聊聊Mustache的循环与条件判断

进入正题之前,我们先来看看何为Mustache.js。在 Github 上的说明如下:

Mustache is a logic-less template syntax. It can be used for HTML, config files, source code – anything. It works by expanding tags in a template using values provided in a hash or object.

We call it “logic-less” because there are no if statements, else clauses, or for loops. Instead there are only tags. Some tags are replaced with a value, some nothing, and others a series of values.

no if statements, else clauses, or for loops ,这句话明确了Mustache模板的特性,在Mustache模板中不可能出现复杂的条件判断。当然,“不可能”并不等于“不能”,Mustache.js可以通过 {{#list}} 循环一个列表,也可以用 {{#key}}{{^key}} 这样的标签进行简单的条件判断。

虽然,这已经能解决我们日常开发中遇到的大多数问题,但是当我们需要在循环中进行一些特殊判断(比如:对第一个元素做特殊处理、对 key 属性做特殊处理、对 id=0 的情况做特殊处理等等)的时候,似乎就不那么好操作了。

使用示例

我们先来看一个Mustache.js的使用示例:

var data = {
title : 'Basic Mustache',
list: [
{name: 'Mr.Zheng', age: 29, sex: 'male'},
{name: 'mailzwj', age: 28},
{name: 'mawuhen', age: 30}, 'String', 2, ['aa', 'bb']
]
},
tpl = '<div><h3>{{title}}</h3>{{#list}}<p>昵称:{{name}},年龄:{{age}}</p>{{/list}}</div>',
wrap = document.getElementById('wrap');
wrap.innerHTML = Mustache.render(tpl, data);

当我们在浏览器中执行这段代码的时候,我们将会得到下图效果:

聊聊Mustache的循环与条件判断

由此可以看出一些问题。第一,最明显的,对于最后三行显示信息,结果并非是我们想要的。第二,对于第一组数据的sex属性并没有进行展示。而对于这些问题,我们可以通过修改模板进行 一定程度 的优化,比如:

<div>
<h3>{{title}}</h3>
{{#list}}
<p>昵称:{{name}},年龄:{{age}}{{#sex}},性别:{{sex}}{{/sex}}</p>
{{/list}}
</div>

但是,对于多条件判断(比如:不存在name,并且不存在age的时候不显示整行)、属性名称和数量不固定以及对第n个元素做特殊处理等情况,修改模板就无能为力了。

循环对象的所有属性

在某些情况下我们可能无法预知后端会返回哪些属性数据,因此我们在模板中无法确定 {{xxx}} 的标签名称,而Mustache.js并没有提供类似JS的 for(key in Obj) 的循环方法,那么我们该怎么应对呢?

查看Mustache.js的文档,在 Non-Empty Lists 这一节有示例,可以在数据对象中添加自定义属性,而属性值以函数的形式对原始数据进行处理,处理完成后返回处理后的结果进行显示。于是,我从这里入手,发现了一个实现方法——还是以前面的数据为例,修改一下模板和JS逻辑:

var main = document.getElementById('main'),
data = {
title : 'Basic Mustache',
list: [
{name: 'Mr.Zheng', age: 29, sex: 'male'},
{name: 'mailzwj', age: 28},
{name: 'mawuhen', age: 30}, 'String', 2, ['aa', 'bb']
]
},
tpl2 = '<div><h3>{{title}}</h3>{{#list}}<p>{{kv}}</p>{{/list}}</div>';
// 循环key, value
data.title = 'Key from data';
data.kv = function() {
var res = [];
// 遍历对象
if (Object.prototype.toString.call(this) === '[object Object]') {
for (var key in this) {
res.push(key + ': ' + this[key]);
}
return res.join(', ');
// 处理数组
} else if (Object.prototype.toString.call(this) === '[object Array]') {
return JSON.stringify(this);
// 处理基础数据类型
} else {
return this;
}
};
main.innerHTML = Mustache.render(tpl2, data);

我们再次通过浏览器查看JS执行结果,我们可以看到以下效果:

聊聊Mustache的循环与条件判断

显然,不仅对列表中的对象进行了所有属性遍历,同时还对列表中的非对象(异常)数据进行了显示。我们也可以对JS逻辑进行修改,对各种类型的数据进行不同的逻辑处理,做更多的事情。不仅如此,如果把握好了这个方法的使用,甚至可以编写子模板一类的扩展功能。

对模板片段书写特殊逻辑

另外,Mustache.js还提供了一个针对模板中的特定片段添加特殊逻辑的方法,能帮助我们完成一些特殊的需求,再以前面的数据为例,我们修改下模板:

var cont = document.getElementById('cont'),
data = {
title : 'Basic Mustache',
list: [
{name: 'Mr.Zheng', age: 29, sex: 'male'},
{name: 'mailzwj', age: 28},
{name: 'mawuhen', age: 30}, 'String', 2, ['aa', 'bb']
]
},
tpl1 = '<div><h3>{{#key}}{{title}}{{/key}}</h3>{{#list}}<p>姓名:{{#key}}{{name}}{{/key}},年龄:{{#key}}{{age}}{{/key}}</p>{{/list}}</div>';

观察模板的变化,我们将 {{title}} 改为了 {{#key}}{{title}}{{/key}} ,同时也在 {{name}}{{age}} 标签外面包裹了 {{#key}}{{/key}} ,接着我们在修改一下我们的JS逻辑:

/**
* item 类似{{title}}的模板片段
* render 是Mustache的渲染模板的方法
*/

data.title = 'Key from template';
data.key = function() {
return function(item, render) {
return item.indexOf('title') > -1 ? '标题:' + render(item) : render(item);
}
};
cont.innerHTML = Mustache.render(tpl1, data);

最终,我们会得到下面的效果:

聊聊Mustache的循环与条件判断

注意,数据中我们设置了 data.title="Key from template" 最终界面上将title标签显示为了“标题:Key from template”,这便是 {{#key}} 提供的功能,可以针对模板的局部区域进行特殊的逻辑处理。

OK,Mustache.js是一个非常轻量级的前端JS模板引擎,但是目前业内有很多比其更加优秀,性能更好,功能更强大的模板引擎。这只是我对于它的一点点思考与尝试,不一定对你有帮助,但如果碰巧给了你一点灵感,我也会很高兴~~

分享到:更多 ()

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址