§模板引擎
§基于 Scala 的类型安全模板引擎
Play 附带了 Twirl,这是一个强大的基于 Scala 的模板引擎,其设计灵感来自 ASP.NET Razor。具体来说,它
- 简洁、表达能力强且流畅:它最大限度地减少了文件中所需的字符和按键次数,并支持快速、流畅的编码工作流程。与大多数模板语法不同,您无需在编码中显式地中断以在 HTML 中指定服务器块。解析器足够智能,可以从您的代码中推断出这一点。这使得语法非常简洁且表达能力强,干净、快速且打字起来很有趣。
- 易于学习:它允许您快速提高工作效率,只需最少的概念。您使用简单的 Scala 结构,并利用您现有的所有 HTML 技能。
- 不是一门新语言:我们有意识地选择不创建一门新语言。相反,我们希望让 Scala 开发人员能够使用他们现有的 Scala 语言技能,并提供一种模板标记语法,使他们能够进行出色的 HTML 构建工作流程。
- 可以在任何文本编辑器中编辑:它不需要特定的工具,使您能够在任何普通的文本编辑器中提高工作效率。
注意: 尽管模板引擎使用 Scala 作为表达式语言,但这对 Java 开发人员来说不是问题。您几乎可以像使用 Java 一样使用它。
请记住,模板不是编写复杂逻辑的地方。您无需在此处编写复杂的 Scala 代码。大多数情况下,您只需访问模型对象中的数据,如下所示
myUser.getProfile().getUsername()
参数类型使用后缀语法指定。泛型类型使用
[]
符号而不是通常的<>
Java 语法指定。例如,您编写List[String]
,它与 Java 中的List<String>
相同。
模板是编译的,因此您将在浏览器中看到任何错误
§概述
Play Scala 模板是一个简单的文本文件,包含少量 Scala 代码块。模板可以生成任何基于文本的格式,例如 HTML、XML 或 CSV。
模板系统旨在让习惯使用 HTML 的用户感到舒适,使前端开发人员能够轻松地使用模板。
模板被编译为标准的 Scala 函数,遵循简单的命名约定。如果您创建一个 views/Application/index.scala.html
模板文件,它将生成一个 views.html.Application.index
类,该类具有一个 render()
方法。
例如,这是一个简单的模板
@(customer: Customer, orders: List[Order])
<h1>Welcome @customer.name!</h1>
<ul>
@for(order <- orders) {
<li>@order.getTitle()</li>
}
</ul>
然后,您可以像通常在类上调用方法一样,从任何 Java 代码中调用它
Content html = views.html.Application.index.render(customer, orders);
§语法:神奇的“@”字符
Scala 模板使用 @
作为唯一的特殊字符。每当遇到此字符时,它都表示动态语句的开始。您无需显式关闭代码块 - 动态语句的结束将从您的代码中推断出来
Hello @customer.getName()!
^^^^^^^^^^^^^^^^^^
Dynamic code
由于模板引擎通过分析您的代码自动检测您的代码块的结束,因此此语法仅支持简单语句。如果您想插入多标记语句,请使用括号显式标记它
Hello @(customer.getFirstName() + customer.getLastName())!
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Dynamic Code
注意: 确保在动态语句的关键字和括号之间不要包含空格。
例如,以下代码不起作用
@for (menu <- menuList) { ... } // Compilation error: '(' expected but ')' found. ^
您也可以使用花括号编写多语句块
Hello @{val name = customer.getFirstName() + customer.getLastName(); name}!
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Dynamic Code
由于 @
是一个特殊字符,因此您有时需要对其进行转义。为此,请使用 @@
My email is bob@@example.com
§模板参数
模板就像一个函数,因此它需要参数,这些参数必须在模板文件的顶部声明
@(customer: models.Customer, orders: List[models.Order])
您也可以为参数使用默认值
@(title: String = "Home")
或者多个参数组
@(title:String)(body: Html)
§模板构造函数
默认情况下,模板被生成为一个静态函数,可以在任何上下文中调用。如果您的模板依赖于组件,例如消息 API,您可能会发现使用组件(和其他模板)注入它更容易,然后您可以将该模板注入使用它的控制器。
Twirl 支持为模板声明构造函数,在文件开头,模板参数之前使用 @this()
语法。构造函数的参数可以与模板参数以相同的方式定义。
@this(messagesApi: MessagesApi)
@(customer: models.Customer, orders: List[models.Order])
§迭代
您可以使用 for
关键字,以一种非常标准的方式
<ul>
@for(p <- products) {
<li>@p.getName() ([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: models.Product) = {
@product.getName() ([email protected]())
}
<ul>
@for(product <- products) {
@display(product)
}
</ul>
请注意,您还可以声明可重用的纯代码块
@title(text: String) = @{
text.split(' ').map(_.capitalize).mkString(" ")
}
<h1>@title("hello world")</h1>
注意: 在模板中以这种方式声明代码块有时可能有用,但请记住,模板不是编写复杂逻辑的最佳位置。通常最好将这些代码外部化到 Java 类中(如果您愿意,可以将其存储在
views/
包下)。
按照惯例,以 implicit 开头的名称定义的可重用块将被标记为 implicit
@implicitFieldConstructor = @{ MyFieldConstructor() }
§声明可重用值
您可以使用 defining
助手定义作用域值
@defining(user.getFirstName() + " " + user.getLastName()) { fullName =>
<div>Hello @fullName</div>
}
§导入语句
您可以在模板(或子模板)的开头导入任何您想要的内容
@(customer: models.Customer, orders: List[models.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>
下一步:使用模板进行依赖注入
发现此文档中的错误? 此页面的源代码可以在 此处 找到。 阅读完 文档指南 后,请随时贡献拉取请求。 有问题或建议要分享? 前往 我们的社区论坛 与社区开始对话。