【发布时间】:2010-11-16 23:06:13
【问题描述】:
我正在开发一个涉及类型层次结构的应用程序,并从通过继承定义每种类型的模型开始。在编写相应的控制器时,我不确定如何以干净的方式处理整个事情。我应该只为能够处理派生模型的基本类型编写一个控制器,还是应该为每个子类型编写一个控制器?应该如何设置视图控制器绑定以与不同的控制器一起使用?
【问题讨论】:
标签: model-view-controller polymorphism sproutcore
我正在开发一个涉及类型层次结构的应用程序,并从通过继承定义每种类型的模型开始。在编写相应的控制器时,我不确定如何以干净的方式处理整个事情。我应该只为能够处理派生模型的基本类型编写一个控制器,还是应该为每个子类型编写一个控制器?应该如何设置视图控制器绑定以与不同的控制器一起使用?
【问题讨论】:
标签: model-view-controller polymorphism sproutcore
您可能想查看 SproutCore 的新实验性多态性支持:http://groups.google.com/group/sproutcore-dev/browse_thread/thread/b63483ab66333d15
【讨论】:
这里有一些关于定义子类和覆盖属性和方法的信息: http://wiki.sproutcore.com/w/page/12412971/Runtime-Objects.
从我(有限)使用 Sproutcore 来看,我只能将 1 个视图绑定到 1 个控制器。
因此,如果您打算使用单个视图(例如 ListView)来显示您的数据,那么我认为您只能将该视图绑定到 1 个控制器。这意味着能够处理派生模型的 1 基类型似乎是要走的路。
【讨论】:
通常,您使用 App.store.find 调用的结果填充 ArrayController 实例的内容。 SC.Store#find 可以采用 SC.Query 实例,通常如下所示:
MyApp.myController.set('content') = MyApp.store.find(SC.Query.local(MyApp.MyModel));
这应该返回 MyApp.MyModel 的所有实例,包括 MyApp.MyModel 的子类的任何实例。
SC.Query.local 的第一个参数可以是 SC.Record 子类或引用子类的字符串。因此,如果您有一些中间 SC.Record 子类,您可能想尝试在那里使用它们。
【讨论】:
在处理模型的单个实例时,控制器应该只是对象的代理。换句话说,ObjectController 可以代理任何东西。这是我在代码中的意思:
你有两个对象,Person 和 Student。
App.Person = SC.Object.extend({
// person stuff here
})
App.Student = App.Person.extend({
// student stuff here, you have have all Person things because you are extending person.
})
然后你想定义控制器:
App.personController = SC.ObjectController.create({
contentBinding: 'App.path.to.person'
})
App.studentController = SC.ObjectController.create({
contentBinding: 'App.path.to.student'
})
请注意,如果人员/学生是选择的结果,或者绑定触发的某些其他流程,您只会将控制器的内容绑定到某些东西。换句话说,如果您手动设置人员(例如从状态图中,作为交互的结果),您仍然会定义控制器,但会做
App.personController.set('content', person);
根据 Person 是应用程序中的“顶级”对象还是某个被选中的中间对象,您可以不同地设置控制器。此外,您可能只需要一个控制器,如果您同时作用于一个人和一个学生,那么您将只有一个 studentController 和一个 personController。两者都只是 ObjectController,它们可以代理任何东西。
最后,在您的视图中,您将相关的视图元素绑定到控制器:
...
nameView: SC.LabelView.design({
layout: {/* props */},
valueBinding: SC.Binding.oneWay('App.personController.name')
})
...
请注意,单向绑定是如果视图上的名称不会更改,如果视图可以更改名称,则只需执行普通绑定即可。还要注意这里的路径。我不绑定
'App.personController.content.name'
由于personController代理了对象,你绑定到
'namespace.controller.property-on-object-controller-proxies'
如果您将大量业务逻辑放入控制器中,那么您做错了。控制器应该只用于代理对象(至少 ObjectControllers 应该是)。业务逻辑应该在模型本身上,决策逻辑应该在状态图中。
【讨论】: