2

问题(有效)

我在我的应用程序中使用 Play 2.1.x 版本。我的应用程序有一个静态标题/工具栏,其中包含登录/注销链接。我没有在所有模板中重复状态标题 html 代码,而是在 main.scala.html 模板中创建了它。现在要更改 SignIn/SignOut 状态,我需要将参数传递给 main.scala.html。如果我是对的,这是我们在游戏中使用的所有模板的父模板,所以如果我们向主模板添加任何参数,它必须由子模板提供,例如索引、登录等(你命名它)

到目前为止,我可以通过在特征中创建隐式 def 并让控制器像这样实现特征来做到这一点(混合组合......)

class ApplicationController extends Controller with ImplicitSession{

}

trait ImplicitSession {
implicit def status(implicit session: play.api.mvc.Session): Boolean = {
session.get("session") match {
  case None => false
  case _ => true
 }
}

让我的所有其他控制器扩展 ApplicationController 而不是只玩控制器

object LoginController extends ApplicationController{...}

现在我的模板参数看起来像这样......

主模板

@(title: String)(content: Html)(implicit status : Boolean)

其他模板,例如登录...

@(message: String)(implicit status : Boolean)

这很好,但我对解决方案不满意,因为它迫使我将这个额外的隐式参数传递给我的所有模板

我真的很想避免将此隐式参数传递给我的所有子模板

因为我觉得这是一个多余的代码,确实不是一个好的编程习惯。所以看起来我脑子里没有清楚这个概念

编译器还强制我将 Action{隐式请求 =>放到我正在创建的所有控制器中,否则它只会引发编译错误

我检查了播放包中提供的示例代码,它们很好,但我对流程的怀疑并不清楚..

提前致谢

4

2 回答 2

1

我真的很想避免将此隐式参数传递给我的所有子模板

答案是无法避免(可悲)。

这是 James Roper(Typesafe 的 Play Framework 开发人员)撰写的一篇出色的博客。

我也使用这种模式,但我更喜欢使用ApplicationContext传递给我所有视图的案例类的名称。

case class ApplicationContext(user: Option[User], moreData: SomeData)

trait ApplicationController extends Controller {
  implicit def context[A](implicit request: Request[A]): ApplicationContext = {
    // Find all necessary data needed
    ...
    ApplicationContext(user, data)
  }
}

然后我的观点通常采用以下参数(包括Lang使用 i18n):

@(message: String)(implicit lang: Lang, context: ApplicationContext)
于 2013-09-17T07:11:55.010 回答
1

为了避免这种情况,我建议不要让每个页面都使用 main.scala.html。

有几种方法可以做到这一点。一种是通过连接,因为您的视图实际上只是返回连接字符串以由结果(Ok、BadRequest 等)包装。

def getStuff = Action { Ok(header.scala.html(someData) + stuff.scala.html()) }

不过这有点难看。

第二种方法是在初始页面加载时发送尽可能少的数据,并使用 AJAX 请求来逐步增强视图。

// 服务器端

def getStuff = Action { Ok(stuff.scala.html()) }

def getMoarStuff = Action { Ok(moarStuff.scala.html(someData)) }

// 客户端

$.ajax({
  method  : "GET",
  url     : "http://localhost:9000/moar/stuff",
  success : function() {
    console.log("got stuff");
  },
  failure:function() {
    console.log("failed");
  }
});

这是单页应用的前提和优势。您可以通过滚动您自己的 AJAX 处理程序(参见上面的愚蠢)或使用 JavaScript 框架(如 Backbone、Ember 或 Angular)来完成此操作。每个都有自己的特点/优点/缺点,但要了解的重要一点是,它们都非常适用于 Play。

于 2013-09-18T01:44:25.513 回答