我在ExtJS 4中遇到过MVC模式的问题。至少,我认为我有。通过这个问题与多个人接触,并在Sencha论坛上多次发布,我现在转向更广泛的受众,希望得到一个灯泡或确认。
问题
您的应用程序可以打开许多不同的视图,其中一些视图本身就是迷你应用程序。此外,用户可能希望打开视图的多个并发副本。
此应用程序是单页客户端Javascript应用程序。
ExtJS 4 MVC模型希望您在Application类中定义所有控制器。然后在应用程序加载时初始化这些控制器。控制器跟踪视图,模型和存储。
多次初始化控制器A时,比如创建一个以上的视图副本,最终会有两个引用相同数据存储的视图,并在功能上将重复事件发送到应用程序事件总线。
我通过向Component和Controller添加新的原型方法来重构我的应用程序,以允许a)子控制器(我的一些控制器变得非常庞大)和b)专门为它们使用的视图定义存储。模型仍然可以在控制器上定义,只是为了方便处理程序使用,如果你需要做一些事情,比如从服务器上获取记录。
问题
我对MVC的理解会让我相信模型与View更直接相关,而不是Controller。 我认为ExtJS 4决定将商店(我认为可以看作是更经典模型的包装)附加到控制器,以鼓励重复使用加载的数据,并优化远离许多副本同一个类实例化。但是,在我看来,如果打算让用户可以使用许多视图实例,则无法执行此操作。根据我的想法,拥有许多实例是OO框架中的一个重要选项,因此我为什么要逆转趋势并在一些Ext基类上实现原型。 (谢谢Ext.implement!)。
是否有任何方法可以使用现成的MVC类并使用提供的setter,getter等来使用加载到其中的不同数据的视图的多个并发实例?
答案 0 :(得分:8)
我遇到了类似的问题:
考虑CRM类型应用程序的tabpanel,它为每个客户端打开视图的新实例。并且说标签视图包含3或4个行编辑网格面板,用于与与该客户端相关的不同数据集合进行交互。
我提出的解决方案基于Sencha论坛的this。在一个坚果shell中,几乎所有从视图调度的事件都包含对视图本身的引用。我的控制器控制功能中的处理程序都使用这些来获取对正确视图实例的引用。
为了处理这个所需的同一商店的多个实例,我从那篇帖子中了解到这一点:
对于视图上的Store实例或全局实例...取决于 需要。如果您打算全球使用,那么将其全局化。如果你 只在视图上需要它然后将它放在视图上。 MVC是 不是法律,你可以改变它以满足你的需要。技术上来说 MVC的控制器部分假设是中间人 查看和建模零件,但有时只是不需要。我创造 95%的时间在视图中存储。我给你举个例子......
如果您有产品商店,则可能只需要参考 存储在网格中。通常不需要其他部分 应用程序。但是,如果你有一个商店来加载国家,我 经常需要它全局,所以我只需要加载一次然后可以 在多个视图中设置/使用该商店。
所以我刚刚在视图的initComponent方法中创建了与视图实例相关的所需商店。该应用程序确实有一些全局商店,我根据MVC建议创建了商店类。很好地将视图实例存储封装在视图中。然后我只需要一个控制器实例。
要具体回答您的问题,目前,没有ExtJS官方推荐或配置来处理使用相同商店构造函数的同一视图的多个实例。我花了一些时间寻找类似的东西,我发现的最好的是他们的论坛版主的推荐。
答案 1 :(得分:2)
我认为您不需要超过1个控制器实例,无论您拥有多少个视图/模型。请参阅此处的功能示例:
http://whatisextjs.com/extjs-4-extension/fieldset-w-dynamic-controls-7
答案 2 :(得分:2)
这可以很容易地完成。你需要遵循一些规则:
在应用启动时加载您的控制器。不要卸载它们。不要担心内存或时间,即使数百个控制器也很小,只要你最小化并连接你的js。
切勿使用控制器的refs或views属性。您将使用一个控制器实例,但是多个视图实例,因此您永远不需要对视图的引用。
仅在控制器中使用事件侦听器。您只会听取您的观看事件。您始终可以通过处理程序中的“cmp”参数获取事件处理程序中视图的(临时)引用。
要“启动”视图,请创建视图并将其添加到另一个视图。为了摧毁它,摧毁它。您不使用控制器来启动视图。您可以使用控制器中的afterrender和beforedestroy事件来添加逻辑。
答案 3 :(得分:1)
在ExtJS的MVC中,控制器是一个单独的视图。我喜欢DeftJS对MVC的看法。视图的每个实例都有一个自己的控制器实例。通过这种方式,您可以将所有“控制规则”放在视图的特定部分的控制器中,并且仅在视图打开时才会实例化。
我没有任何经验可以在同一个项目中使用多个Defts JS应用程序。
答案 4 :(得分:0)
当然。是什么导致你不相信? 以下是创建从Window组件扩展的自定义View的示例。您可以从同一个控制器多次运行此方法,每次获取View的新实例。
“this”指代码运行的控制器:
this.getRequestModel().load(requestID,{ //load from server (async)
success: function(record, operation) {
var view = Ext.widget('requestEdit',{
title: 'MyRequest '+requestID
});
var form = view.down('form');
form.loadRecord(record);
}
});
答案 5 :(得分:0)
您如何创建自己的观点?我认为没有理由不能将不同的商店或配置数据传递给每个对象。一些代码示例将有助于您正在做什么。例如,我们有一个类似的声音应用程序,一切都是通过扩展完成的。所以,如果我们需要一个网格,我们就运行
Ext.define('MyApp.grids.something',{
extends:'Ext.grid.panel'
//...
这些类是预定义的。然后,当控制器或视图加载此网格时,它们正在使用
var grid=Ext.create('MyApp.grids.something',{id:'unique',store:mystore});
如您所见,我们可以在每次创建时将不同的配置选项传递到同一网格。我们可以像处理
那样对待这个Ext.create('Ext.grid.Panel');
当然,除了我们预定义了一些选项,还有一些不可覆盖的选项,等等。
希望这会有所帮助。
答案 6 :(得分:0)
结帐this post。我们的想法是从视图配置中进行一些配置(如store
和itemId
)并将其放入视口配置中:
// .../app/view/Viewport.js
Ext.define('MyApp.view.Viewport', {
// ...
items: [
// ...
{ xtype: 'testview', store: 'Store1', itemId: 'instance1' },
{ xtype: 'testview', store: 'Store2', itemId: 'instance2' }
]
});
显然,商店的问题将得到解决。不同的itemId
将使您能够正确处理事件。