天天看点

PrvtCMS制作网站,使用模板引擎(mustache.js)作服务端渲染

作者:PrvtSite

在这个重复造轮子的时代,新的技术每时每刻可能都在诞生。起初是想做一个构建工具,结果写了一个简单的内容管理系统(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

人人为我,我为人人,一起加油吧。

继续阅读