Play 2.0 用户指南 - 模版引擎 -- 针对Scala开发者

原创
2012/03/19 17:09
阅读数 1.4K


一个基于Scala的类型安全的模版引擎


    Play2.0带来了一个全新的真正强大的基于Scala的模版引擎。该引擎的设计灵感源于ASP.NET Razor.特别是:

        简洁,富有表达力,流畅:最小化语法字符和击键要求,让你快速,流畅的编写代码。不像大多数模版引擎的语法,你无须明确的中断HTML代码就可嵌入服务器端逻辑。引擎会智能 的为你识别。这是一个真正简洁,富有表达力的语语法,使输入变得干净,快速,愉快。

        易于学习:掌握简单的概念就能让你快速产出。它使用你已掌握的Scala和HTML技能。
        非新语言:我们极力避免创造一门新语言。相反,我们想使开发人员能够利用其现有的Scala语言技能,在你选择的语言下提供一个HTML结构工作流程的模板标记语法。
        可使用任何文本编辑器:不需要特别的编辑工具,旧的文本编辑器也可轻松工作。

    模版会被编译,因此你可以在浏览器中看到任何编译错误。

   

概述


    Play Scala 模版是简单的文本文件,它包含简短的Scala代码块。它可以生成任何的文本格式,HTML,XML,CVS。
   模版系统已被设计成可以自然舒适的处理HTML,使得web设计师们能轻松的工作。

    模版会被编译成标准的Scala函数,遵循简单的命名约定:如果你创建了一个 views/Application/index.scala.html 模版文件,它將产生一个  views.html.Application.index 函数。
    例如,下面这个简单的模版:
@(customer: Customer, orders: Seq[Order])
 
<h1>Welcome @customer.name!</h1>

<ul> 
@orders.map { order =>
  <li>@order.title</li>
} 
</ul>

    你可以在你的任何Scala代码中,像函数一样调用它:
val html = views.html.Application.index(customer, orders)

语法:充满魔力的‘@’字符


    Scala模版使用 @ 作为单独,特殊的字符。每当遇到该字符,便是指示这是Scala代码块的开始。不需要明确的关闭该代码块 - 模版会根据代码自动推断:
Hello @customer.name!
       ^^^^^^^^^^^^^
        Scala code


    因为模版引擎通过分析源码自动检测代码块结尾处,所以它仅仅支持简单的声明块。如果你想插入多块声明,请明确的用括号标记:
Hello @(customer.firstName + customer.lastName)!
       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 
                    Scala Code


    你也可以使用纯正的Scala语法,使用大括号标记多块声明:
Hello @{val name = customer.firstName + customer.lastName; name}!
       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
                             Scala Code


    由于 @ 是特殊字符,有时候你需要转义。像这样 @@ :
My email is bob@@example.com

    模版参数


    模版是一个普通函数,所以它需要参数,参数必须声明在模版文件的第一行:
 
@(customer: models.Customer, orders: Seq[models.Order])
    你也可以指定参数默认值:
@(title: String = "Home")
    或者甚至是参数组:
@(title:String)(body: => Html)
    甚至一个隐式参数:
    
@(title: String)(body: => Html)(implicit request: play.api.mvc.Request)

    迭代

    你可以使用 Scala 的for-comprehension,以很表标的方式。但注意,编译器会自动在你的代码块前面加上 yield 关键字:
<ul>
@for(p <- products) {
  <li>@p.name ($@p.price)</li>
} 
</ul>


    你可能意识到了,该for仅仅是经典的map形式的语法糖:
<ul>
@products.map { p =>
  <li>@p.name ($@p.price)</li>
} 
</ul>

    

    if块

    if块也没什么特别。简单的使用标准的 Scala if 声明:
@if(items.isEmpty) {
  <h1>Nothing to display</h1>
} else {
  <h1>@items.size items!</h1>
}


    模式匹配


    你也可以在模版中使用模式匹配:
@connected match {
    
  case models.Admin(name) => {
    <span class="admin">Connected as admin (@name)</span>
  }

  case models.User(name) => {
    <span>Connected as @name</span>
  }
    
}


    定义可重用块


    你可以定义可重用代码块:
@display(product: models.Product) = {
  @product.name ($@product.price)
}
 
<ul>
@products.map { p =>
  @display(product = p)
} 
</ul>


    注意你也可以用纯Scala方式声明可重用代码块:
@title(text: String) = @{
  text.split(' ').map(_.capitalize).mkString(" ")
}
 
<h1>@title("hello world")</h1>


    注意:这种方式声明的代码块某些时候可能很有用,但谨记,模块不是一个编写复杂逻辑的好地方。它通常都应该提取到外部的Scala文件中。(如果你愿意,出可以保存在views/目录中)

    依照惯例,以 implicit 开头的可重用块会被标记为 隐式的:
@implicitFieldConstructor = @{ MyFieldConstructor() }


    声明可重用值


    你可以使用 define 定义范围变量值:
@defining(user.firstName + " " + user.lastName) { fullName =>
  <div>Hello @fullName</div>
}


    导入声明


    你可以在模版开头(或子模块)处按需导入声明:
@(customer: models.Customer, orders: Seq[models.Order])
 
@import utils._
 
...


    注释

    在服务器端编写注释,你可以使用 @* *@:
@*********************
 * 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>


    Scala模版的常见用例


    模版,作为普通函数,可通过任何方式组合。下面是一些常用的场景例子。

    布局


    让我们声明一个 views/main.scala.html 模版,它將作为主要布局模版: 

@(title: String)(content: Html)
<!DOCTYPE html>
<html>
  <head>
    <title>@title</title>
  </head>
  <body>
    <section class="content">@content</section>
  </body>
</html>

    你看到,该模版需要两个参数:title 和 Html 内容块。我们可以在另一个 views/Application/index.scala.html 中使用它:
@main(title = "Home") {
    
  <h1>Home page</h1>
    
}

    注意:我们有时命名参数为@main(title = "Home"),有时候为@main("Home")。依你所好,在不同的场景中选择更简洁的形式。

    有时候,你需要另一个页面特定的内容,例如边栏或者页脚。你可以指定另一个参数:
@(title: String)(sidebar: Html)(content: Html)
<!DOCTYPE html>
<html>
  <head>
    <title>@title</title>
  </head>
  <body>
    <section class="sidebar">@sidebar</section>
    <section class="content">@content</section>
  </body>
</html>


    在我们的'index'模版中使用它,需要:
@main("Home") {
  <h1>Sidebar</h1>

} {
  <h1>Home page</h1>

}

    另外,我们可以单独声明边栏:
@sidebar = {
  <h1>Sidebar</h1>
}

@main("Home")(sidebar) {
  <h1>Home page</h1>

}

    标签(它们也不过是函数,不是吗?)

    让我们编写一个简单的 views/tags/notice.scala.html 标签,显示HTML通知:

    现在,让我们在另一个模版中使用它:
@(level: String = "error")(body: (String) => Html)
 
@level match {
    
  case "success" => {
    <p class="success">
      @body("green")
    </p>
  }

  case "warning" => {
    <p class="warning">
      @body("orange")
    </p>
  }

  case "error" => {
    <p class="error">
      @body("red")
    </p>
  }
    
}

    包含

    同样,这也没什么特别。你可以调用任何你需要的模版(实际上是来自任何地方的函数都可以):
<h1>Home</h1>
 
<div id="side">
  @common.sideBar()
</div>


展开阅读全文
加载中
点击引领话题📣 发布并加入讨论🔥
打赏
0 评论
2 收藏
1
分享
返回顶部
顶部