模板引擎
基于Scala类型安全的模板引擎
Play自带有 Twirl,这是一个强大的基于Scala的模板引擎,它的设计灵感来自ASP.NET Razor,更具体的说是:
- 简洁, 富有表现力, 和流畅: 它把字符的数量和在文件中点击键盘的需求降至最低,并且实现了快速,流畅的编程工作流。不像大多数模板语法,你完全不需要为了在HTML代码中明确表示服务端的语句块,而中断你的编码。足够聪明的解析器可以从你的代码中推断出这点。这让这个真正的紧凑并富有表现力的语法变的简洁,快速和有趣。
- 易于学习:它可以让你用最少的概念,快速的提高效率。你可以使用简单的Scala结构和所有你会的HTML技能。
- 不是一个新的语音:我们自觉的没有创建一个新的语言,相反,我想让Scala开发人员可以使用他们已有的Scala语音技能,并提供一个模板标记语法,让完美的HTML构建工作流成为可能。
- 可在任何文本编辑器中编辑:它不需要一个特殊的工具,可以让你在任何普通的旧文本编辑器中提高效率。
模板是可以被编译的,因此你可以在你的浏览器中看到任何错误:
概述
Play的scala模板是一个包含了小的Scala代码块的简单的文本文件。模板可以生成任何基于文本的格式,如HTML,XML或者CSV。
模板系统的设计,让使用HTML的人感到舒服,让前端开发者很容易的使用模板。
模板是被做为标准的Scala函数编译的,遵循简单的命名规范。如果你创建iews/Application/index.scala.html 模板文件,它将会生成有 apply方法的views.html.Application.index类。
例如,这是一个简单的模板:
@(customer: Customer, orders: List[Order])
<h1>Welcome @customer.name!</h1>
<ul>
@for(order <- orders) {
<li>@order.title</li>
}
</ul>
然后你就可以从任何Scala代码中调用这个,就像一般你调用类的方法:
val content = views.html.Application.index(c, o)
语法:不可思议的 ‘@’字符
Scala模板使用 @ 做为单独的特殊字符。每次遇到这个字符,就表示动态语句的开始。你不需要显式的关闭代码块——将会从你的代码中推断动态语句的结束:
Hello @customer.name!
^^^^^^^^^^^^^
Dynamic code
由于模板引擎自动的通过分析你的代码,探测你的代码块的结束,因此这个语法只支持简单的语句。如果你想插入多令牌语句,就要使用括号显式的标记出来:
Hello @(customer.firstName + customer.lastName)!
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Dynamic Code
你可以可以使用大括号,写多语句块:
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)
迭代
可以以标准的方式使用for关键字:
<ul>
@for(p <- products) {
<li>@p.name ($@p.price)</li>
}
</ul>
注意:确保{和for在同一行,来表示表达式继续到下一行。
If-blocks
If-blocks 没有什么特别的地方。简单的使用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>
注意你也可以声明一个可复用的纯代码块:
@title(text: String) = @{
text.split(' ').map(_.capitalize).mkString(" ")
}
<h1>@title("hello world")</h1>
注意:用这种方式在模板中声明代码块有时有用,但是要记住模板不是写复杂逻辑的最佳地方。往往更好的方式的在Scala类(如果你想写,你可以存储在 views/包下)中写这样的代码。
按照规范,以implicit 开始的命名的可复用的代码块将被标记为 implicit:
@implicitFieldConstructor = @{ MyFieldConstructor() }
声明可复用的值
你可以使用defining 助手定义值的作用域:
@defining(user.firstName + " " + user.lastName) { fullName =>
<div>Hello @fullName</div>
}
导入语句
你可以在模板(或子模板)的开头导入任何你想要的类:
@(customer: Customer, orders: List[Order])
@import utils._
...
为了避免意外, 在导入语句中使用root 语法:
@import _root_.company.product.core._
如果你需要在所有的模板中导入常用的导入,你可以在 build.sbt文件中声明:
TwirlKeys.templateImports += "org.abc.backend._"
注释
你可以在模板中使用 @* *@写服务端的注释块:
@*********************
* This is a comment *
*********************@
你可以在第一行放一段注释把你的模板记录进Scala API文档:
@*************************************
* Home page. *
* *
* @param msg The message to display *
*************************************@
@(msg: String)
<h1>@msg</h1>
转义
默认情况下,动态部分的内容会根据模板类型(如HTML或XML)的规则被转义。如果你想输出一个原生的内容段,并把它封装进模板内容类型。例如输出原生的HTML:
<p>
@Html(article.content)
</p>