天天看點

PrvtCMS制作網站,使用模闆引擎(mustache.js)作服務端渲染

在這個重複造輪子的時代,新的技術每時每刻可能都在誕生。起初是想做一個建構工具,結果寫了一個簡單的内容管理系統(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

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

繼續閱讀