第一:
HTTL只有六个指令:#set, #if, #else, #for, #break, #macro,并且不会增加。
<!--## 定义变量类型,未定义的变量以Object类型处理 -->
<!--#set(User user, List<Book> books)-->
<html>
<body>
<!--## 定义宏,可当变量或方法执行 -->
<!--#macro(cover(Book book))-->
<img alt="${book.title}" src="${book.cover}" />
<!--#end-->
<!--## 条件判断 -->
<!--#if(user.role =="admin")-->
<table>
<!--## 循环输出,类型可省,将基于泛型推导 -->
<!--#for(Book book : books)-->
<tr>
<!--## 变量输出 -->
<td>${book.title}</td>
<!--## 执行宏输出,也可以用${cover} -->
<td>$!{cover(book)}</td>
<!--## 变量赋值,类型可省,将基于表达式推导 -->
<!--#set(int price = book.price * book.discount)-->
<td>${price}</td>
</tr>
<!--## 条件中断循环 -->
<!--#break(for.index == 10)-->
<!--## 当循环数据为空时执行 -->
<!--#else-->
没有数据。
<!--#end-->
</table>
<!--#else(user)-->
没有权限。
<!--#else-->
没有登录。
<!--#end-->
</body>
</html>
变量指令
#set变量类型
声明变量的类型,模板内部其它变量类型基于此类型推导。
1
2
3
4
5
|
格式: #set(type
name, type name) 示例: #set(User
user, List< Book >
books) |
注:暂时只支持List和Map的一级泛型,多级泛型能解析,但不能推导。
多次设置变量的类型,如果类型为父子关系,以子类型优先:
1
2
|
#set(ParentClass
var1) #set(ChildClass
var1) |
不管先后顺序,都以子类型优先:
1
2
|
#set(ChildClass
var1) #set(ParentClass
var1) |
如果是两个完全不同的类型,将报错:
1
2
|
#set(OriginClass
var1) #set(DiffrentClass
var1) |
#set变量赋值
将表达式的计算结果存入变量中。
1
2
3
4
5
6
7
8
9
10
|
格式: #set(name
= expression) #set(type
name = expression) #set(name
:= expression) #set(type
name := expression) 示例: #set(price
= book.price * book.discount) #set(int
price = book.price * book.discount) |
注意,为了简化模板的书写,#set的变量全模板有效,不限制在块指令内:
1
2
3
4
|
#if(xxx) #set(var
="value") // 变量全模板有效,而不是if块内有效 #end ${var}
// 可以访问到if块内var的值 |
不需要像Java那样:
1
2
3
4
5
|
#set(var
= null) #if(xxx) #set(var
="value") #end ${var} |
类型的声明,同时可以用作强制转型,比如:
1
|
#set(Book
book = bookentry.value) |
如果bookentry.value的类型丢失,上面的写法可以恢复book的类型。
一个set指令可同时有多个类型声明或赋值,用逗号分隔,但类型声明和赋值要分开写,如:
1
2
|
#set(User
user, List< Book >
books) #set(price
= book.price, discount = book.discount) |
赋值会在生成局部变量的同时,写入当前Context中, 如果有include()子模板,在子模板中也可以读到该变量。
指令对比
Velocity | HTTL | 异同 | 功能 | 变化 |
${xxx.yyy} $xxx.yyy | ${xxx.yyy} | 相同 | 输出占位符 | HTTL大括号必需 |
$!{xxx.yyy} $!xxx.yyy | $!{xxx.yyy} | 不同 | 空值不显示源码 |
VM为空值不显示源码 HTTL改为不过滤输出 |
## ... #* ... *# |
## ... #* ... *# | 相同 | 不显示注释块 | |
#[[ ... ]]# | #[ ... ]# | 相似 | 不解析文本块 | HTTL少一对方括号 |
\# \$ \\ | \# \$ \\ | 相同 | 特殊符转义 | |
#set($xxx = $yyy) |
#set(xxx = yyy) #set(Type xxx = yyy) #set(Type xxx) | 相同 | 给变量赋值 | HTTL可带类型声明 |
#if($xxx == $yyy) | #if(xxx == yyy) | 相同 | 条件判断 | |
#elseif($xxx == $yyy) | #else(xxx == yyy) | 相似 | 否则条件判断 | HTTL复用#else指令 |
#else | #else | 相同 | 否则判断 | |
#end |
#end #endif #end(if) | 相同 | 结束指令 | HTTL可带配对指令名 |
#foreach($item in $list) |
#for(item : list) #for(Type item : list) | 相似 | 列表循环 | HTTL改为Java格式 |
#break |
#break #break(xxx == yyy) | 相同 | 中断循环 | HTTL可以直接带条件 |
#stop |
#break #break(xxx == yyy) | 相似 | 停止模板解析 | HTTL复用#break指令 |
#macro($xxx) | #macro(xxx) | 不同 | 可复用模板片段宏 |
VM将宏作为指令执行 HTTL作为函数执行 |
#define($xxx) | #macro(xxx = xxxmacro) | 相似 | 捕获块输出到变量中 | HTTL复用#macro指令 |
#include("xxx.txt") | ${read("xxx.txt")} | 相似 | 读取文本文件内容 | HTTL改为函数扩展 |
#parse("xxx.vm") | ${include("xxx.httl")} | 相似 | 包含另一模板输出 | HTTL改为函数扩展 |
#evaluate("${1 + 2}") | ${render("${1 + 2}")} | 相似 | 模板求值 | HTTL改为函数扩展 |