为什么Playframework 2使用自定义Scala模板引擎而不是在xml模式下构建scala?

时间:2012-06-01 14:51:52

标签: template-engine playframework-2.0 design-decisions

Play 2.0使用基于scala的自定义模板引擎,允许在html代码中使用scala的子集。

为什么要做出这个设计决策而不是使用scalas内置xml模式?

播放模板引擎有一些缺点,如

  • 仅支持scala的一个子集,例如,似乎无法在函数内定义函数
  • 在eclipse中没有编辑支持

另一方面,我知道play scala模板引擎支持非格式化的html,这对于scalas xml模式是不可能的,但我想应该总是可以在一个良好的形式中编写模板办法。我只是一个游戏和scala的初学者,只想了解背景。

2 个答案:

答案 0 :(得分:1)

我认为它有几个答案:

  1. 这是一个模板。模板不应该包含复杂的逻辑。所有逻辑操作都必须在控制器/模型中完成。

  2. 模板可以包含您想要的任何格式:电子邮件,CSV,SQL等。将模板限制为有效的XML实际上限制了框架的可能性。

  3. 一切都是可编辑的。甚至路由,资产,模板继承等。为了使这些机制可以与框架的其余部分一起工作,可能必须做出一些选择。但没有人能够比框架的创建者更好地回答你。

答案 1 :(得分:1)

一个原因可能是scala中xml中属性的笨拙处理。有两个问题:

  1. “已选择”之类的属性必须存在或不存在
  2. 动态添加属性列表,如输入助手模板的htmlArgs
  3. 简单scala中的一个例子显示了困难:

    def addAttributes(element: Elem, attributes: Map[Symbol, _ <: Any]): Elem = {
        var el = element
        for ((key, value) <- attributes) el = el % Attribute(None, key.name, Text(value.toString), Null)
        el
      }
    
      def multiselect[T](field: play.api.data.Field,
        options: Seq[T],
        optionValue: T => String,
        optionText: T => String,
        args: (Symbol, Any)*)(implicit handler: FieldConstructor, lang: play.api.i18n.Lang) = {
        val values = { field.indexes.map { v => field("[" + v + "]").value } }
        input(field, args: _*) {
          (id, name, value, htmlArgs) =>
            Html(
              addAttributes(
                <select id={ id } name={ name } multiple="multiple">
                  {
                    options.map { v =>
                      val z: Option[String] = if (values contains v) Some("selected") else None
                      <option value={ optionValue(v) } selected={ z map Text }>{ optionText(v) }</option>
                    }
                  }
                </select>,
                htmlArgs).toString)
        }
      }