第一轮排除
在上次node模板引擎简单比較的文章里。事实上已经有个简单的筛选了。总结成规则应该是这种:
最后在 Template Chooser 上依据条件选择下来,就剩这些了:
基本上就剩下 mustache 系了
尽管之前也接触了一些的模板引擎,传统的比方 PHP 的 Smarty。Java 的 Velocity,甚至曾经公司里跨平台的火麒麟等,但我还是承认看过一次 mustache 就对这个系列产生了偏好,那么接下来就具体分析一下他的一些特性。
mustache类引擎特性分析
长处是简洁, if
/ for
都能够通吃。但缺点是依赖于必选变量,非常难将推断条件其扩展成表达式。另外 for
的索引变量名也无法设置。
当 #xxx
是一个 Object 类型值时。是应该依照 if
存在推断还是依照 for-in
遍历?眼下是推断存在并创建下级作用域,这就导致无法使用 Object 类型作为 Map 进行 for-in
遍历。
另一点,假设是在进行一个 list 的循环时,无法定义循环项和索引的变量名。非常难利用到索引这个特殊变量。只是在 GRMustache 的实现中有增强,能够使用 @index
特殊变量,但这不是一个比較好的解决方式。
#
模块生成了子级作用域,使模块内的子级变量得到简写。缺点是设计渲染引擎的时候可能对于scope的情况考虑起来比較复杂,比方不同层次的同名变量,有可能会导致性能问题。
*[En]*
**
{
* {{variable}}
{/}
*[En]*
**
因为条件推断都合并到了 #
符号的语句中。而推断因为要简化多种形式。导致不能使用表达式。而 mustache 仅仅设计了 ^
用来取反的一种表达方式,实际上和 #
都没有不论什么关联,在表达能力上就比較不足,比方想用 else
就非常麻烦。
if
类似 switch/case
的多条件分支就更难实现,尽管用的也不多,可是还是会有一定机会。
在 mustache 里仅仅有一种,就是引入模板片段,类似于其它引擎的 include。符号是 {{>partial}}
。
*[En]*
**
另外除了Handlebars其它也不支持继承形式的模板复用。所以我之前写了MustLayout这个npm包来在express中预处理这两个缺陷。
变量在 mustache 中很easy,差点儿仅仅有模板替换的功能。
*[En]*
**
对照其它模板引擎的突出特性
如 liquid/Smarty/Swig 等中,能够在渲染模板时创建暂时变量,在某些情况下有一定的便利性。
*[En]*
**
这个特性一定程度上也能够由函数模板来完毕。
在 liquid/Smarty/Swig/Etpl 等中,能够通过类似 *nix shell 的管道模式,对要输出的变量进行很多其它处理,比方日期格式化。编码转义等功能。
{{ aDate | date(‘Y-m-d') }}
在继承 block 块时能够使用父模板中已定义的部分。方便的追加很多其它内容,比方 CSS 和 JS 的引用部分:
{% block head %}
{% parent %}
<span class="tag"><<span class="title">link</span> <span class="attribute">rel</span>=<span class="value">"stylesheet"</span> <span class="attribute">href</span>=<span class="value">"custom.css"</span>></span>
{% endblock %}
Dust.js 的继承方式看起来比較诡异,是使用一个正常理解应该是 include 的方式来实现的。并且符号也是从 mustache 系继承过来的 {>parent}
,而只在之后定义 block 区块,对父模板进行覆盖来实现。从实现的角度看这是一个比較取巧的方式,由于假设不过声明 layout 。那么声明语句究竟放在模板的哪里比較合适?假设声明两次是否会造成问题?而通过引入的话就比較直白了,无论如何这是必须写的且只会写一次。我是要用父模板。先拿进来。之后的 block 部分实际上是重名再次定义的赋值过程。
issue里甚至有人提到这样的写法应该使用开闭标签。让 {>parent}…{/parent}
之间包括其block的内容,也有道理,可是写起来是略有复杂,不够直白。
在 include 一个模板片段时代入一个自己定义的块。以覆盖片段中的部分内容。这给 block 除了向上继承以外很多其它的一种灵活性。
<span class="tag"><<span class="title">div</span> <span class="attribute">class</span>=<span class="value">"list"</span>></span>list<span class="tag">div</span>>
<span class="tag"><<span class="title">div</span> <span class="attribute">class</span>=<span class="value">"pager"</span>></span>pager<span class="tag">div</span>>
在 Etpl 中称为过滤器,眼下用例是将 Markdown 格式的模板内容转换成HTML,有一定价值。但不一定是必须功能,能够考虑作为扩展实现。
## markdown document
This is the content, also I can use `${variables}`
期待 mustache 增强的特性
对照了那么多,事实上说对 mustache 最基本的偏好还是来自于模板语言表达的间接性,而对于他最核心的轻逻辑来说。有点太轻。尽管我不须要完整的原生语言控制,但轻的难以表达了就还是须要权衡。
*[En]*
**
最基本的变量还是使用双括号,而控制语句使用但括号+特殊字符,同一时候关闭能够为自结束。而且不须要写相应的关闭标签名。
使用双括号在模板中输出变量:
{{ variable }}
{{ nested.element }}
{{ array[index] }}
{{ <span class="keyword">object</span>[key] }}
输出能够使用带运算符的简单表达式:
{{ ok ? <span class="number">1</span> : <span class="number">0</span> }}
{{ ok || <span class="string">'none'</span> }}
{{ <span class="keyword">index</span> * (<span class="keyword">x</span> + <span class="number">3</span>) }}
能够使用过滤器管道:
{{ variable | escapeHTML }}
{{ today | date:<span class="string">'Y-m-d'</span> }}
{{ <span class="keyword">group</span> | max }}
默认不进行 HTML 转义。这样能够支持很多其它情景,而不是 HTML 专属。相反使用三括号才进行默认转义:
{{{ content }}}
能够使用等号 =
进行暂时变量赋值,但赋值使用专门的 $
符号语句且须要自关闭符号:
{<span class="variable">$ </span>x = y * <span class="number">5</span> /}
{<span class="variable">$ </span>obj = {<span class="symbol">a:</span> <span class="number">1</span>, <span class="symbol">b:</span> []} /}
*[En]*
**
尽管 mustache 的 #
功能非常强大。但表达能力略有欠缺且easy造成歧义,所以我还是把条件分支单独拿出来。
if
语法用问号开头表达,和条件表达式一样有疑问的意思:
{? expression }
<span class="literal">true</span>
{/}
{? !condition }
<span class="literal">false</span>
{/}
else
语法借用原来的 ^
符号,且不再能够单独使用这个取反符号:
{? expression}
<span class="literal">true</span>
{^}
<span class="literal">false</span>
{/}
else if
类型的多条件继续使用 ^
符号进行额外推断:
{? case1 }
1
{^ case2 }
2
{^}
-1
{/}
临时没想到怎样简洁的表达对同一条件的 switch/case
表达,先用 else
结构取代。
if
普通的 for
循环继续使用 #
,但添加迭代条目和索引暂时变量声明:
{# list:item@index }
<span class="tag"><<span class="title">li</span>></span>{{ index }}: {{ item }}<span class="tag">li</span>>
{/}
循环能够针对普通数组。也能够针对 Object 类型的对象:
{# map:value@key }
<span class="tag"><<span class="title">li</span>></span>{{ key }}: {{ value }}<span class="tag">li</span>>
{/}
能够联合取反符号 ^
使用。输出没有元素项时的内容:
{
{{ item }}
{^}
none items :(
{/}
内嵌模板片段:
{> partialName /}
模板名称能够在 API 中分情况实现。比方在后端 node.js 环境中,模板名直接相应相对路径进行文件读取;而在前端假设是使用 ``
Original: https://www.cnblogs.com/yfceshi/p/7403948.html
Author: yfceshi
Title: Node.js模板引擎的深入探讨
相关阅读
Title: C# DES (ECB模式) 加密解密 --单倍长
加密: 调用时: Encrypt_DES16("2AF349243535BCD3", "1111111111111111");
public static string Encrypt_DES16(string str_in_data, string str_DES_KEY) //数据为十六进制
{
try
{
byte[] shuju = new byte[8];
byte[] keys = new byte[8];
for (int i = 0; i < 8; i++)
{
shuju[i] = Convert.ToByte(str_in_data.Substring(i * 2, 2), 16);
keys[i] = Convert.ToByte(str_DES_KEY.Substring(i * 2, 2), 16);
}
DES desEncrypt = new DESCryptoServiceProvider();
desEncrypt.Mode = CipherMode.ECB;
//desEncrypt.Key = ASCIIEncoding.ASCII.GetBytes(str_DES_KEY);
desEncrypt.Key = keys;
byte[] Buffer;
Buffer = shuju;//ASCIIEncoding.ASCII.GetBytes(str_in_data);
ICryptoTransform transForm = desEncrypt.CreateEncryptor();
byte[] R;
R = transForm.TransformFinalBlock(Buffer, 0, Buffer.Length);
string return_str = "";
foreach (byte b in R)
{
return_str += b.ToString("X2");
}
return_str = return_str.Substring(0, 16);
return return_str;
}
catch (Exception e)
{
throw e;
}
}
解密:调用时: Encrypt_DES16("C47EC89B0A247A47", "1111111111111111");
//DES解密
public static string Decrypt_DES16(string str_in_data, string str_DES_KEY)//数据和密钥为十六进制
{
byte[] shuju = new byte[8];
byte[] keys = new byte[8];
for (int i = 0; i < 8; i++)
{
shuju[i] = Convert.ToByte(str_in_data.Substring(i * 2, 2), 16);
keys[i] = Convert.ToByte(str_DES_KEY.Substring(i * 2, 2), 16);
}
DES desDecrypt = new DESCryptoServiceProvider();
desDecrypt.Mode = CipherMode.ECB;
desDecrypt.Key = keys;
desDecrypt.Padding = System.Security.Cryptography.PaddingMode.None;
byte[] Buffer = shuju;
ICryptoTransform transForm = desDecrypt.CreateDecryptor();
byte[] R;
R = transForm.TransformFinalBlock(Buffer, 0, Buffer.Length);
string return_str = "";
foreach (byte b in R)
{
return_str += b.ToString("X2");
}
return return_str;
}
Original: https://www.cnblogs.com/yxwkf/p/5424481.html
Author: yxwkaifa
Title: C# DES (ECB模式) 加密解密 --单倍长