在这个重复造轮子的时代,新的技术每时每刻可能都在诞生。起初是想做一个构建工具,结果写了一个简单的内容管理系统(PrvtCMS),目前使用mustache.js作服务端渲染。
本着物尽其用的原则,我们不仅要使用,还要创造更深入的用法。现在让我们一起进入编程世界吧。
github地址:https://github.com/janl/mustache.js
基本语法
名称 | 使用方法 |
变量 | {{content}} |
带有HTML的变量 | {{{content}}} |
循环 | {{#navs}} ...... {{/navs}} {{#keys}} {{.}} {{/keys}} 数组循环的时候可以用 . 作为下标 |
if else | {{#loginStatus}} ...... {{/loginStatus}} {{^loginStatus}} ...... {{/loginStatus}} |
布尔判断 | 和前面循环的语法是一样的,取决于变量是否是一个数组 {{#data}} ...... {{/data}} |
数组的布尔判断 | {{#datas.length}} ...... {{/datas.length}} |
Lambdas | 遇到和前面的循环和布尔表达式一样,取决于参数的类型 {{#person}} {{name}} is awesome. {{/person}} |
两个核心方法 | Mustache.parse(template); Mustache.render(template, obj); |
基本用法
<script src="/libs/mustache.js/4.1.0/mustache.min.js"></script>
<script type="text/javascript">
const obj = {title: '热门推荐'};
const template = '您当前正在访问:{{title}}。';
const res = Mustache.render(template, obj);
console.log(res);
// 您当前正在访问:热门推荐。
</script>
循环的使用
<script type="text/javascript">
const navs = [
{ id: '1', title: '首页' },
{ id: '2', title: '产品管理', child: [
{ id: '3', title: '办公设备' }
]}
];
const obj = { navs: navs };
const template = `
<ul>
{{#navs}}
<li>
<a href="/list?navid={{id}}">{{title}}</a>
{{#child.length}}
<ul>
{{#child}}
<li>
<a href="/list?navid={{id}}">{{title}}</a>
</li>
{{/child}}
</ul>
{{/child.length}}
</li>
{{/navs}}
</ul>
`;
const res = Mustache.render(template, obj);
console.log(res);
/**
<ul>
<li>
<a href="/list?navid=1">首页</a>
</li>
<li>
<a href="/list?navid=2">产品管理</a>
<ul>
<li>
<a href="/list?navid=3">办公设备</a>
</li>
</ul>
</li>
</ul>
*/
</script>
Lambdas自定义函数
官方实例
<script type="text/javascript">
const obj = {
"name": "Willy",
"person": function() {
return function(text, render) {
return "<b>" + render(text) + "</b>"
}
}
};
const template = `{{#person}} {{name}} is awesome. {{/person}}`;
const res = Mustache.render(template, obj);
console.log(res);
//<b> Willy is awesome. </b>
</script>
假设我们现在有一个需求,不显示个人中心导航。
这是PrvtCMS内部的功能实现,如果您有更好的方式,欢迎交流。
<script type="text/javascript">
const obj = {
navs: [
{ id: '1', title: '首页' },
{ id: '9', title: '个人中心' }
],
arrayFunctions: function() {
return function(text, render) {
const options = this;
const conditions = text.match(/(?<={{#)\w+=>[^}]+(?=}})/gi) || [];
if(!conditions || !conditions .length) return render(text);
const key = conditions[0];
const fns = key.match(/(?<=\=\>)[a-z]+[\(][^\)]+[\)]/gi) || [];
let datas = [];
fns.map(fn => {
const attrKey = (key.match(/^\w+/) || [''])[0];
const dataCds = fn.match(/(?<=[\s\(])\w+([=]+(["']).*?(?<=[^\\])\2)*/g);
if (attrKey) {
if (/^filter/.test(fn)) {
const filtercdn = fn.replace(/^\w+\(/, '').replace(/\)$/, '');
const filters = filtercdn.match(/^([\(\!&\|]*\w+[!=<>]+((["']).*?(?<=[^\\])\3|true|false|\d+)[\)]*)+$/);
if (filters && filters.length) {
if (((options)[attrKey])) {
datas = ((options)[attrKey]).filter((data) => {
return eval(filtercdn.replace(/((?<=[\(&\|])|^)\w+/g, (str) => 'data.' + str));
})
}
}
}
}
});
(options)[key] = datas;
return render(text);
}
}
};
const template = `
<ul>
{{#arrayFunctions}}{{#navs=>filter(title!='个人中心')}}
<li><a href="/list?navid={{id}}">{{title}}</a></li>
{{/navs=>filter(title!='个人中心')}}
{{/arrayFunctions}}
</ul>
`;
const res = Mustache.render(template, obj);
console.log(res);
/**
<ul>
<li><a href="/list?navid=1">首页</a></li>
</ul>
*/
</script>
服务端与前端共用组件
PrvtCMS目前服务端与前端共用组件采用的方式。
服务端:{%title%}
客户端:{{data.title}}
// 服务端先处理
const navs = [
{ id: '1', title: '首页', type:1 },
{ id: '2', title: '产品管理', type: 3}
];
const options = { navs: navs };
const template = `
<ul>
{%#navs%}
<li :class="getNavClass({%type%})">
<a href="/list?navid={%id%}">{%title%}</a>
</li>
{%/navs%}
</ul>
`;
Mustache.render(template, options, {}, ['{%', '%}']);
//前端处理
{
// data ...
getNavClass(type){
// ...
}
// ...
}
在线演练
网址:https://www.prvt.site/mustache.js
人人为我,我为人人,一起加油吧。