§模板引擎
§基于 Scala 的类型安全模板引擎
Play 附带了 Twirl,这是一个强大的基于 Scala 的模板引擎,其设计灵感来自 ASP.NET Razor。具体来说,它
- 简洁、表达能力强且流畅:它最大限度地减少了文件中所需的字符和按键次数,并支持快速、流畅的编码工作流程。与大多数模板语法不同,您不需要在代码中显式地标记服务器块来中断您的编码。解析器足够智能,可以从您的代码中推断出这一点。这使得语法非常简洁且表达能力强,干净、快速且有趣。
- 易于学习:它允许您在最少的概念下快速提高工作效率。您可以使用简单的 Scala 结构,并利用您现有的所有 HTML 技能。
- 不是一门新语言:我们有意识地选择不创建一门新语言。相反,我们希望让 Scala 开发人员能够使用他们现有的 Scala 语言技能,并提供一种模板标记语法,使 HTML 构建工作流程变得更加出色。
- 可以在任何文本编辑器中编辑:它不需要特定的工具,并允许您在任何普通的文本编辑器中提高工作效率。
模板是编译的,因此您将在浏览器中看到任何错误。
§概述
Play Scala 模板是一个简单的文本文件,其中包含少量 Scala 代码块。模板可以生成任何基于文本的格式,例如 HTML、XML 或 CSV。
模板系统的设计旨在让习惯使用 HTML 的人感到舒适,允许前端开发人员轻松地使用模板。
模板被编译成标准的 Scala 函数,遵循简单的命名约定。如果你创建一个名为 views/Application/index.scala.html
的模板文件,它将生成一个名为 views.html.Application.index
的类,该类包含一个 apply()
方法。
例如,以下是一个简单的模板
@(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
注意: 确保动态语句的关键字和括号之间不要包含空格。
例如,以下代码不起作用
@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,你可能会发现用它需要的组件(和其他模板)注入它更容易,然后你可以将该模板注入到使用它的控制器中。
Twirl 支持为模板声明构造函数,在文件开头使用 @this()
语法,在模板参数之前。构造函数的参数可以与模板参数以相同的方式定义
@this(myComponent: MyComponent)
@(customer: Customer, orders: List[Order])
§迭代
你可以使用 for
关键字,以一种非常标准的方式
<ul>
@for(p <- products) {
<li>@p.name ([email protected])</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 ([email protected])
}
<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 的安全隐患,如果用户有可能控制内容。此技术是跨站点脚本 (XSS) 漏洞的常见原因,如果不谨慎使用,则很危险。
例如,要输出原始 HTML
<p>
@Html(article.content)
</p>
§字符串插值
模板引擎可以用作 字符串插值器。您基本上用“$”替换“@”
import play.twirl.api.StringInterpolation
val name = "Martin"
val p = html"<p>Hello $name</p>"
§显示 Scala 类型
Twirl 通常通过调用 Scala 类型的值的 toString
方法来渲染它们。但是,如果值包装在 Option
或集合(Seq
、Array
、TraversableOnce
)中,Twirl 会先解开值,然后调用 toString
。
例如,
<ul>
<li>@Option("value inside option")</li>
<li>@List("first", "last")</li>
<li>@User("Foo", "Bar")</li>
<li>@List("hello", User("Foo", "Bar"), Option("value inside option"), List("first", "last"))</li>
</ul>
在浏览器中呈现为
下一步:模板的依赖注入
发现本文档中的错误?此页面的源代码可以在这里找到 这里。在阅读 文档指南 后,请随时贡献拉取请求。有疑问或建议要分享?前往 我们的社区论坛 与社区开始对话。