doT是一个性能非常高的JavaScript模板,可以用于nodeJs和web端。 该项目在github上开源:github.com/olado/doT,官网内容相对简单,国内也没有太过详细的使用说明(可能是因为上手确实太简单了)。
由于官网文档对于如何在node端和web端使用doT说明的比较详细,这里就不再赘述。重点说明一下doT的编译和语法。
doT compile
doT渲染模板分为2个阶段,这一点从它的使用方法中也能看出来:
var tempFn = doT.template(“<div>{{= it.foo}}</div>”);
var resultText = tempFn({foo: ‘hello world'});
这一点是与其他主流的模板引擎不同的。
在compile阶段,可以依赖其他模板文件,缓存模板等操作。还可以传入参数,通过条件判断生成模板内容。
在页面载入或是服务器启动时,根据一些环境变量或其他条件预先编译模板,可以进一步提高模板渲染是的效率。
doT.template
方法的第2个参数为配置项,第3个参数为编译时可接收的参数,参数在模板中被默认存储在def
对象下,具体用法在{{#}}
语法中介绍。
doT.template
方法返回值为function
类型:tempFn
,tempFn
接收的参数是模板渲染时可传入的数据(与前面编译时的数据不是同一份数据)。该数据在模板中被默认存储在it
对象下具体用法在{{}}
和{{=}}
等语法中都会介绍。
默认语法
下面的例子以web客户端为运行环境,例子中调用的全局变量的例子都是Bom下的window对象内容。如果是nodejs,则对应的全局变量有差异,但道理是一样的。
提供一个比较简单的doT模板在线编辑网站:kakanjau.github.io/dot
{{ }}
{{ }} interpolation 代码片段
{{ }} 的用法非常灵活,里面可以直接写js语句。定义的变量可以直接在{{= }}
中调用。也可以调用通过tempFn
传入的数据(数据默认放在it对象内)。
// 模板字符串:
{{
var a = 1;
it.a = a + 1;
}}
{{= a}} // a 输出 1
{{= it.a}} // it.a 输出 2
也可以定义函数。并在其他的{{}}
区块内调用:
// 模板字符串:
{{
function fn() {
return 123
}
}}
{{= fn()}} // fn 输出 123
也可以直接运行匿名函数
{{
(function() {
it.b = 123
})();
}}
{{= it.b}} // it.b通过直接执行的匿名函数赋值为123
{{}}
中的代码块随时可以被打断,插入dom片段等html内容:
// 模板字符串:
{{
var a = 3;
if(a > 2) {
}}
a的值大于2
{{
} else {
}}
a的值小于2
{{
}
}}
此外,{{}}
中也可以直接调用全局对象下的函数或变量。可以以此特点实现比较复杂的功能(通过专用的命名空间给doT模板提供一些过滤器等特色的支持等)。
! 如果在
tempFn
函数的调用中不传参数或者传入的是undefined
等空对象,则doT不会实例化it
对象。此时在{{}}
中赋值的it对象的值,{{=}}
中无法拿到(js的值引用问题)。
{{= }}
{{= }} evaluation 输出表达式 {{= }}
将其中的内容直接输出到html中。其中可以是在{{ }}
中定义的变量、通过函数传入在it
中的变量、也可以是全局变量、甚至可以是一个立即执行的function的返回结果。
可以简单的理解为可以获取特定作用于下变量的单行js语句:
// 模板字符串:
{{
it.a = 1;
a = 2;
}}
{{= it.a}} it.a = 1
{{= a}} a = 2
{{= window}} window = [object Window]
{{= (function(){return 123})()}} function(){return 123})() = 123
{{! }}
{{! }} encode 转义
{{! }} 会将其中的内容中特定字符进行转义,如:{{! location.href}}
{{? }}
{{? }} conditionals 条件
{{?}}标签必须成对出现,起始标签中写入判断条件,并以另外一个{{?}}
标签为结束。该标签和下面的{{~}}
是{{if for}}
的语法糖。
如上面的:
// 模板字符串:
{{
var a = 3;
if(a > 2) {
}}
a的值大于2
{{
} else {
}}
a的值小于2
{{
}
}}
可以用本标签简写为:
// 模板字符串:
{{
var a = 3;
}}
{{? a>2}}
a的值大于2
{{?? true}}
a的值小于2
{{?}}
{{~ }}
// 模板字符串:
{{
var array = [1,2,3,4];
}}
{{~ array:value:index}}
value:{{=value}}, index:{{=index}}
{{~}}
{{~}} array iteration 循环
{{~}}标签必须成对出现,起始标签中写入对数组遍历的变量赋值:{{~it.array :value:index}}
,并以另外一个{{~}}
标签为结束。
{{# }}
{{#}} compile-time evalution/includes and partials 编译时载入代码片段、文件
类似于宏编译,在compile阶段,将对应的变量或文件内容插入指定的位置
传入的参数默认在对象def
中。此外,通过{{## #}}
定义的变量,也都是在def
对象中的
用法与{{}}
基本一致,只是生效的阶段不同。
ps: 虽然官方文档中提到了
{{#def.loadfile(‘/snippet.text')}}
这样载入模板的例子。但其实这一功能并不是默认集成的。loadfile函数需要自己去实现,并通过参数传入。
所以在使用doT时,可以考虑通过插件等形式封装的时候,给def、it提供一些默认的行为方法
{{## #}}
{{## #}} compile-time defines 编译时变量定义
{{## #}}有两种赋值方式:使用=
赋值和使用:
赋值。二者的区别是,=
赋值时,右侧是一个js的表达式。可以是函数定义、真值判断、字符串等等,:
赋值时,紧跟:
之后的所有内容,都被当做静态模板直接赋值给变量:
// 模板字符串:
{{##
def.array = [1,2,3,4]
#}}
{{#def.array[0]}} 的值是 1
{{##
def.array2:[1,2,3,4]
#}}
{{#def.array2[0]}} 的值是 [ // array2是字符串的:”[1,2,3,4]”,所以第0位是 [