把TinyTemplate当成是Velocity的升级版其实也是可以的,毕竟它的语法是基到Veloccity扩展而来的,兼容度在80%以上。
至于TinyTemplate的实例是怎样的,且看下面:
宏的可变参数
在Java中的可变参数使用起来非常方便,Tiny模板也对可变参有一定支持。
#macro hello()
ParameterList: ${helloParameterList.size()}
#for(para:helloParameterList)
hello:${para}
#end
#end
#call("hello","aa",1,true,false)
运行结果:
ParameterList: 4
hello:aa
hello:1
hello:true
hello:false
说明:在宏的包体中,有一个默认的变量,名称就是宏的名字+ParameterList,当前例子中,宏的名字是hello,所以变量的名字就是:helloParameterList。
此变量的类似是一个List,因此可以调用List的方法。
Set示例
运行结果:宏定义及其调用示例
1:1
2:2
3:1
4:2
5:2
解释:
首先设置abc=1,然后显示它的值,结果是1,这个是理所当然的。
然后定义一个宏,在宏里设置变量abc的值为2,然后显示这个值。
在调用setAbc宏的时候,果然显示出来abc的值为2,这个也是没有问题的。
接下来再显示abc的值的时候,结果是1,为什么呢?
这是因为在Tiny宏中引入了变量范围的概念,也就是说在宏里面的变量是局部变量 ,对于宏外的变量没有影响。
因此,在宏里的#set指令并没有改变了外层的abc的值,因此第三个输出的结果是1
接下来在setAbc2宏里用#!set指令进行赋值,赋值为2,因此第四个输出了结果2
由于#!set修改的是模板级的变量,所以,它就修改了外部变量的值为2,所以第五个输出的结果也是2.
好的,上面就介绍清楚了这些概念,那么问题来了:
下面的宏,输出结果是什么?
答案a:没有任何输出,答案b:输出1,亲们在下面回答下?
宏定义及其调用示例
运行结果:
Hello1,world
Hello1,world
Hello2,world
Hello2,world
我是附加内容
Hello3,world
Hello4,world
代码解释:
#macro是定义宏的指令,后面哪着一个关键字作为宏的名字,括号内是参数,参数可以有多个,也可以一个没有。
在#macro当中,可以有一个占位符#bodyContent,表示调用的时候在宏头和#end之间的内容会被放在这里。
调用的时候,也有两种调法一种是“#宏名(...)”,另外一种是"#@宏名(...)#end"的方式。
带@的表示是有宏体调用,不带@表示是简单调用。
与Velocity不同,调用宏,后面必须跟小括号,不能省略。
#@hello1("world")
我是附加内容
#end
上面这段有加内容,但是由于在定义宏时没有点位符,因此“我是附加内容”被忽略。
#@hello2("world")
我是附加内容
#end
这里由于hello2宏定义时有#bodyContent占位符,所以就可以显示出来。
注意,宏定义,可以放在任何位置,且没有任何区别,和调用顺序没有关系,也就是可以在前面调用后面定义的宏。
也就是说
#macro hello3(name)
Hello3,${name}
#macro hello4(name)
Hello4,${name}
#end
#end
和
#macro hello3(name)
Hello3,${name}
#end
#macro hello4(name)
Hello4,${name}
#end
没有任何区别
宏定义及其调用进阶示例
运行结果
hello,World
hello,john
Good morning,World
代码解释:
在Tiny模板引擎中,定义宏时,可以为宏定义默认的参数值,当调用宏的时候,如果没有传入指定的值,则会取其默认值
当然下面的调用方式,也是支持的:
#hello("Good afternoon","john")
#hello(info="Good afternoon","john")
#hello(name="john",info="Good afternoon")
宏定义及其调用之嵌套定义
运行结果
<div class="class1">
<div class="class2">
HelloWorld
</div>
</div>
解说:在Tiny模板引擎中,宏定义的时候,可以嵌套使用其它的带带包体的宏,而在Velocity中是不支持这样写的。
此功能极大的方便了宏的编写及复用,乃是本人对Velocity无法忍受之功能特性之一,在Tiny模板引擎中完美支持。
Tiny模板中的内容显示
#set(abc="<b>Hello</b>")
1:${abc}
2:$!{abc}
运行结果
1:<b>Hello</b>
2:<b>Hello</b>
说明:
显示内容有两种,一种是${} 一种是$!{}
第一种是原样显示,第二种是进行html,xml转码。
Tiny模板之注释
##单行注释
#*
多行注释
*#
#--
多行注释
--#
#**
文档注释
*#
Tiny模板引擎强制不解析标记
用#[[ ]]#包含起来的内容,不进行语法解析,会原样输出。
适用于里面有许多语义冲突的内容,避免使用字符转义
Tiny模板引擎之IF
运行结果:
1:info
3:info
4:info
7:info
8:info
如果真,当然就成立了,所有有1:info
由于abc没有定义,所以就不成立,所以就没有2:info
对于boolean类型看真假,对于非布尔型,看是不是null,如果不是null,那么就成立,于是有3:info,8:info
由于"abc"为真,true为真,!false为真,所以 真&&真||真=真,所以有4:info
因为abc=1,所以,有7:info
Tiny模板语言之循环
运行结果:
sample1:1
sample2:1
sample2:2
sample2:3
sample3:abc
sample4:DefaultInfo
sample5:1
sample5:2
sample5:3
sample6:1
sample6:3
sample7:1
详细解释:
任何对象,都可以进行循环操作。
但是不同的对象循环时的效果不同:
如果是null,则不执行循环体。
如果是Map,则循环变量存放其entry,可以用循环变量.key、循环变量.value的方式读取其中的值
如果是Collection或Array则循环变量放其中的元素
如果是Enumeration、Iterator,则循环变量存放其下一个变量。
如果是enum类,则循环变量存放其枚举值
否则,则把对象作为循环对象,但是只循环一次
Tiny模板引擎之布局
首先写个布局文件如下:
接下来写3个页面:
下面是运行结果:
a.page
这里是A的header
这里是a文件
这里是A的Footer
b.page
这里是B的header
这里是b文件
这里是B的Footer
c.page
这里是c的header
这里是c文件
这里是默认的Footer
在布局文件中,可以用#layout指令定义布局位置,在页面文件中可以通过#@layout来进行实现。
如果在页面文件中没有定义某个布局位置的内容,则使用在布局文件中默认的内容。
Tiny模板引擎之调用宏的N种写法
解释:
宏在Tiny模板引擎中有着巨大的作用,对宏的调用方式也有多种支持方式:
- #宏名,#@宏名方式
- #call(宏名表达式)#@call(宏名表达式)
- ${call(宏名表达式)}
第一种方法:直接,方便,尽量使用。
第二种方法:主要用于宏名是动态的时候,要调用宏名要根据参数来确定调用哪个的时候使用。
第三种方法:用得比较少,用于通过函数调用来进行宏渲染(这种不支持带包体调用)
另外:带@的时候,可以带包体调用(宏里有#bodyContent),不带@的时候,不带包体调用。
Tiny模板引擎之宏默认值
运行结果:
<div id="abc" style="width:800;height:600;">
Hello,World
</div>
Box1
<div id="box1" style="width:800;height:600;">
Box2
<div id="box2" style="width:800;height:600;">
HelloWorld
</div>
</div>
解释:只要在声明宏的时候指定了默认参数,但是在实际使用的时候没有指定,或者指定了,但是是null,则都会使用默认值进行使用。
这样会大大方便编写宏。
如果不支持默认值 ,则在编写宏的时候,要等价的写为:
哪个复杂、哪个方便不辩自明
Tiny模板引擎之格式严格控制
#for( i :[ 1 .. 3 ])
${i}#eol
#[
#for( j :[ 1 .. 3 ])
#t${i}*${j}={i*j}#eol
#end
#]
#end
运行结果:
1
1*1={i*j}
1*2={i*j}
1*3={i*j}
2
2*1={i*j}
2*2={i*j}
2*3={i*j}
3
3*1={i*j}
3*2={i*j}
3*3={i*j}
解说,通过上面的标记可以对格式进行格式控制,这样就可以输出自己期望的结果,而不必担心有一些模板控制指令周边的空格影响结果。
如何快速编写并运行Tiny模板
说到模板开发,当然就离不开要调试,要运行。
由于一般情况下模板语言都是由Java程序驱动跑的,因此,每次都需要搞一个Java类或搭建一个Web环境来驱动它,才能运行出结果。这个对于悠然来讲,是不可忍受的。因此,TinyTemplate必须要可以快速开发,快速运行。
首先编写一个模板文件
33table.page
#for(i:[1..2])
#for(j:[1..2])
${i}*${j}=${i*j}#eol
#end
#end
然后在资源管理器中,选中33table.page,点鼠标右键,然后选择运行方式,在运行方式里选择TinyTemplate:
在控制台就可以看到运行结果了:
1*1=1
1*2=2
2*1=2
2*2=4
当然,如果想进行调试,也是可以进行调试的,只要把生成源码的目录设置成源代码目录即
可。
这个时候的开发效率,就是一个字:快;这个时候的心情,就是一个字:爽。
有时候,要测试的模板文件是需要外部参数的,这个时候怎么测试呢?
只要在运行参数中添加一段html方式URL(格式aa=1&bb=3)内容传参即可:
比如宏内容如下:
Hello,${name}
在运行窗口的参数中添加参数:
name=World
运行结果就是Hello,World
Tiny模板引擎之配套开发工具
要想做一流的模板引擎,当然有一流的模板编辑器是必须的。
Tiny模板引擎推出已经有一段时间了,但是由于其语法是独立的,因此编辑只能采用一般的文本编辑器,但是编辑效率自然就低。还有一种是采用Velocity编辑器进行编辑,但是带来的问题经常会有错误的语法提示,有些语法无法正确提示,总而言之言而总之,就是不好用。那问题已经来了,咋办?答案当然是最好有一个自己的了。
现在,Tiny模板引擎的专有编辑器来了!
特性介绍
- 大纲支持:支持在大纲当中显示一些关键内容,并可以快速定位
- 语法高亮:支持在编辑器中,根据语法进行着色,使得代码更容易阅读和排错
- 错误提示:如果模板语言存在错误,则可以在工程导航、错误视图及编辑窗口进行错误提示
- 代码折叠:支持对代码块进行代码折叠,方便查阅
- 语法提示:支持Tiny模板引擎语法提示及Html语法提示方便快速录入
- 快速定位:支持Tiny模板中开始语句与结束语句间快速切换
- 变量快速提示:点鼠标点击某变量时,会高亮显示文件中的所有同名变量
- 宏定义对应位置显示:在tiny块处理的标签头部按ctrl时,会高亮显示与其对应的#end,反之亦然
- 格式化:可以按快捷键ctrl+shift+F进行格式化了
- 注释处理:可以按快捷键ctrl+/来进行快速设置单行注释或取消单行注释,可以按ctrl+shift+/来进行快速设置块注释或取消块注释
截图介绍
大纲支持,现在支持宏定义,布局定义,布局实现,变量定义四种,可以通过双击大纲树中的节点,快速定位并选定相关的内容
语法着色,这里的颜色是我自己乱配的,仅用于展示效果,后面会让美工仔细配配颜色
错误提示,当写的模板有错误的时候,在项目导航,编辑窗口及错误视图中都会同步显示:
点击编辑器前面的X,可以显示详细的错误信息:
代码折叠
语法提示
也支持模糊匹配,可以看到输入了oc,实际上就过滤了只包含包含o和c的提示内容
除了模板语言的提示,也支持Html语法的支持:
当然,对html的支持不能仅仅是支持标签,属性也要支持:
快速切换:
当用ctrl+鼠标左键点击#end时,会快速定位到对应的宏标签头部,当用ctrl+鼠标左键点击宏标签头部时,可以快速定位到对应的#end。
同名变量显示,点击一个变量时,同名变量会高亮显示
当在块头或块尾按Ctrl键时,对应的块尾或块头会高亮显示,便于快速定位。
格式化之前
格式化之后
快速注释示例
总结
Tiny模板引擎如果从功能来说,比Velocity强大多了;从性能来说,是Velocity的4倍左右;从开发工具来说,比最强大的Velocity工开工具都强。
所以,综合来说,把TinyTemplate说成Velocity Plus还是比较贴切的。