一、语法
1.@
它是一个特殊的字符,表示动态声明的开始。对于简单的动态声明结尾可以从代码块中自动推断结尾,对于复杂的表达式通常加上()
Hello @(customer.firstName + customer.lastName)!
注意: 在关键字、动态声明和参数之间不能有空格,否则会编译错误
也可以使用大括号来编写多语句块:
Hello @{val name = customer.firstName + customer.lastName; name}!
因为@
是一个特殊的字符,需要规避它,需要的情况下使用@@来转义
My email is bob@@example.com
2.参数
必须在模板的顶部,可以有默认参数,也可以有多个参数
@(customer: Customer, orders: List[Order]) @(title: String = "Home") @(title: String)(body: Html)
3.构造器
Twirl支持构造器,可以通过模板顶部什么@this()
字符(要在参数声明之前)来创建构造器。构造器的参数声明方式与模板参数一致。
@this(myComponent: MyComponent) @(customer: Customer, orders: List[Order])
4.for与if
for,if与{ 必须在同一行
<ul> @for(p <- products) { <li>@p.name ($@p.price)</li> } </ul>
@if(items.isEmpty) { <h1>Nothing to display</h1> } else { <h1>@items.size items!</h1> }
5.重复使用
@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>
通常的,以隐式开头的名称定义的可重用块将被标记为implicit
@implicitFieldConstructor = @{ MyFieldConstructor() }
声明可重用值时,可以通过defining定义域
@defining(user.firstName + " " + user.lastName) { fullName => <div>Hello @fullName</div> }
6.import语句
可以在任何位置使用import语句
@import utils._
可以使用root前缀来使用绝对路径
@import _root_.company.product.core._
一些所有模板都会使用的通用引用,可以在buid.sbt文件中声明
TwirlKeys.templateImports += "org.abc.backend._"
7.注释
@* *@
在第一行注释时可以生成Scala API文档
@************************************* * Home page. * * * * @param msg The message to display * *************************************@ @(msg: String) <h1>@msg</h1>
8.转义
默认情况下,动态内容根据模板类型(例如HTML或XML)规则进行转义。如果要输出原始内容片段,请将其包装在模板内容类型中
<p>@Html(article.content)</p>
9.字符串插值
模板引擎可以用作字符串插值器。把“@”换成“$”即可
import play.twirl.api.StringInterpolation val name = "Martin" val p = html"<p>Hello $name</p>"
10.可直接解析被包裹在Option
或集合(Seq
,Array
,TraversableOnce
)里的值
二、依赖注入
通过使用构造器,模板可以被生成为一个class而不是一个静态对象。这就意味着模板可以被直接注入到Controller中,并且可以自己管理依赖。而不是controller既管理自己的依赖又管理模板的依赖
假设模板依赖于组件Summarizer
,而这个组件不会被Controller使用
trait Summarizer { /** Provide short form of string if over a certain length */ def summarize(item: String) }
创建一个模板文件 app/views/IndexTemplate.scala.html
@this(summarizer: Summarizer) @(item: String) @{summarizer.summarize(item)} And finally define the controller in Play by injecting the template in the constructor: public MyController @Inject()(template: views.html.IndexTemplate, cc: ControllerComponents) extends AbstractController(cc) { def index = Action { implicit request => val item = "some extremely long text" Ok(template(item)) } }
通过这种方式,Controller不用得知Summarizer
的存在,模版可以自己管理依赖信息。
如果在Play以外的框架中使用Twirl,需要用以下方式添加注解
TwirlKeys.constructorAnnotations += "@javax.inject.Inject()"