基于Scala的类型安全的模板引擎
Play提供了基于Scala的强大模板引擎Twirl。它的诞生灵感来自于 ASP.NET Razor。它有如下特点:
- 简洁、流畅、富于表现力:它能让你尽可能少的打字,同时提供了一个快速流畅的编码体验。与很多其他模板引擎不同之处在于在HTML中不会有服务端的代码块来打断编码节奏。聪明的解析器会自动推断出期望的结果,这种好处带来的直接后果就是简洁而干净的代码,快速,且富于乐趣。
- 易上手:只包含了一些简单的概念,让你很快就能上手写代码。你可以使用简单的Scala结构和所有现有的HTML技能。
- 不是一个新语言:我们特意选择了不创造一门新的语言。而尽可能的保留了Scala语言的特性,通过模板标记语法来支持一个出色的HTML构建工作流。
- 文本编辑器友好:不需要任何特殊的工具,使用普通的文本编辑器也可以出色的工作。
注意:虽然模板引擎使用了Scala作为描述语言,这对Java开发者来说也不是问题。你可以像使用Java那样来用它。记住不要在模板中写复杂的业务逻辑。这里不需要复杂的Scala代码,大多数情况下你只需要接受数据而已,如: myUser.getProfile().getUsername()。
参数类型通过前缀来限定。泛型使用[],而不是Java的<>。如List[String]相当于Java里面的List<String>。
模板需要经过编译,所以你可以直接在浏览器上看到错误信息:
概述
Play Scala 模板就是一个简单的包含着Scala代码的文本。模板可以生成任意的文本格式,如 HTML、XML或者CSV。
模板被设计为HTML友好的,因此前端开发人员可以直接在模板上工作。
模板被当成标准的Scala函数来编译,只是加入了一些简单的命名约定。如果创建了一个 view/Application/index.scala.html,将编译生成一个包含着render()方法,名为views.html.Application.index 的class文件:
@(customer: Customer, orders: List[Order])
<h1>Welcome @customer.name!</h1>
<ul>
@for(order <- orders) {
<li>@order.title</li>
}
</ul>
你可以在任意Java code中调用他,就像调用其他class中的普通方法一样:
Content html = views.html.Application.index.render(customer, orders);
语法:神奇的'@'
Scala模板将'@'视作特殊符号。每当出现 @ 暗示着后边跟着动态表达式。你不需要显式地关闭代码块——编译器会自动推断它:
Hello @customer.getName()!
模板引擎将自动检测代码结束,因此这种语法只支持简单的表达式。如果你需要插入复杂的表达式,你需要显式的将它们放入括号中:
Hello @(customer.getFirstName() + customer.getLastName())!
注意:需要确保在关键字和动态表达式及括号之间不能加入空格,如下面的表达式将不起作用:
@for (menu <- menuList) { ... } // Compilation error: '(' expected but ')' found.
^
你也可以使用大括号:
Hello @{val name = customer.firstName + customer.lastName; name}!
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Dynamic Code
如果需要使用@字符,可以用@来对它进行转义:
My email is bob@@example.com
模板参数
模板和函数类似,同样也需要参数,这些参数需要在模板顶部进行声明:
@(customer: Customer, orders: List[Order])
也可以设置默认值:
@(title: String = "Home")
甚至设置参数组:
@(title: String)(body: Html)
模板构造函数
通常模板由一个静态方法创建。但如果你的模板依赖于其它的组件(如消息API),可能注入是更好的选择,包括将组件注入模板,及将模板注入controller。
Twirl 支持为模板声明构造函数。你可以在模板最开始、其它参数之前使用 @this() 语法。构造函数的参数的定义形式和模板参数一样:
@this(myComponent: MyComponent)
@(customer: Customer, orders: List[Order])
迭代
使用 for 关键字来迭代,下面是标准用法:
<ul>
@for(p <- products) {
<li>@p.name ($@p.price)</li>
}
</ul>
注意:确保 { 和 for 在同一行,这样可以告知编译器表达式将从下一行开始。
if 块
if表达式没有任何特殊之处,就是Scala的if语句:
@if(items.isEmpty) {
<h1>Nothing to display</h1>
} else {
<h1>@items.size items!</h1>
}
声明可重用的代码块
可以像下面这样声明可重用代码块:
@display(product: Product) = {
@product.name ($@product.price)
}
<ul>
@for(product <- products) {
@display(product)
}
</ul>
也可以声明可重用的纯Scala代码:
@title(text: String) = @{
text.split(' ').map(_.capitalize).mkString(" ")
}
<h1>@title("hello world")</h1>
注意:声明代码块有时是一种简单的实现方式,但是请记住模板并不是实现业务逻辑的地方。最好把它抽出来放到外部代码中。
我们约定以 implicit 命名开头的方法,将被视作隐式方法:
@implicitFieldConstructor = @{ MyFieldConstructor() }
声明重用的value
你可以使用defining帮助类来定义域变量:
@defining(user.firstName + " " + user.lastName) { fullName =>
<div>Hello @fullName</div>
}
导入语句
你可以在template开始出导入任意你想要的东西:
@(customer: Customer, orders: List[Order])
@import utils._
...
想以绝对地址导入,在语句前增加root前缀:
@import _root_.company.product.core._
如果需要在所有template中导入,可以在sbt中声明全局配置:
TwirlKeys.templateImports += "org.abc.backend._"
注释
以 @* *@ 包含的代码块将被视作注释:
@*********************
* This is a comment *
*********************@
如果将注释放在template的第一行,将生成Scala API doc:
@*************************************
* Home page. *
* *
* @param msg The message to display *
*************************************@
@(msg: String)
<h1>@msg</h1>
转义
默认,动态内容将根据模板类型进行自动转义(如 HTML或者XML)。如果你希望展示原始内容,请将它们包装金template content类型中。
下面的例子将输出原生的HTML:
<p>
@Html(article.content)
</p>
来源:oschina
链接:https://my.oschina.net/u/140355/blog/2413977