【四 Twirl模板引擎】 1. 模板引擎

ε祈祈猫儿з 提交于 2019-11-30 05:29:35

基于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>
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!