为什么在play2 scala模板中构建的html会生成一个空的html case类



为什么输出"html为空"?

@h = {<br />}
@h match {
  case Html("") => {html is empty}
  case _ => {html has content}
}

并输出"html有内容"?

@i = @{Html("<br />")}
@i match {
  case Html("") => {html is empty}
  case _ => {html has content}
}

这对我来说很重要的原因是,在上一个例子的常见用例(moreScripts和moreStyles等价物)中,第一个样式用于将一堆html传递到另一个模板中。然后我想根据html是否有内容进行切换。但它总是与Html(")匹配。

为每个方法生成的代码略有不同。

def h:play.api.templates.Html = {
  _display_(
    Seq[Any](format.raw("""<br />"""))
  )
}
def i = {{Html("<br />")}}

用于创建h_display_方法最终对传入的Seq 的所有元素执行foldLeft

这导致:

Html("") + Html("<br />")

事实证明,Html case类是由一个可变的StringBuilder支持的。

case class Html(text: String) extends Appendable[Html] with Content with play.mvc.Content {
  val buffer = new StringBuilder(text)
  /**
   * Appends this HTML fragment to another.
   */
  def +(other: Html): Html = {
    buffer.append(other.buffer)
    this
  }
  override def toString = buffer.toString
  /**
   * Content type of HTML (`text/html`).
   */
  def contentType: String = "text/html"
  def body: String = toString
}

这意味着text的值只会被设置为第一个Htmltext的值。无论何时通过+方法创建新的Html,都只能修改StringBuilder

例如

val html = Html("1") + Html("2")
html.text == "1"
html.toString == "12"
html.body == "12"

由于text值用于模式匹配,这有效地破坏了其用于模式匹配的能力。

例如

(Html("1") + Html("2")) match { case Html("1") => "broken" } // returns "broken"

也许可以尝试进行字符串匹配?

@h.toString() match {
  case "" => {html is empty}
  case _ => {html has content}
}

最新更新